JAVA中多线程基础知识
程序(软件):数据和指令的集合。软件架构:B/S C/S 软件分类:系统软件,应用软件。
进程:正在运行的程序,会在内存中分配空间。
线程:进程中的多条路径。
多线程是指有多条线程并发的执行。
并发:多条线程在同一时间段内交替执行。
并行:多条线程同时执行。
创建线程:
1.继承:extends Thread类 继承的子类需要重写run方法
2.实现:implements Runnable接口
注意:无论是继承还是实现,直接调用重写过的run方法是无法开启多线程的,jvm中默认start()方法开启多线程,start()方法会默认调用重写的run()方法。
3.线程创建方式的优缺点:
① 继承方式写法简单。实现方式写法相对比较复杂
② 继承与实现都是通过 start 方法才能开启线程。
③ 继承的扩展性和灵活性都低于实现方式的扩展性和灵活性
④ 继承的方式,耦合度高于实现的方式。
实际开发中,使用实现形式要多于继承形式。
使用继承来开启多线程 :代码示例:
1 package com.Allen.Thread; 2 3 public class Demo5 { 4 public static void main(String[] args) { 5 ExtendsThread et=new ExtendsThread(); 6 et.start(); 7 for(int j=0;j<100;j++) { 8 System.out.println("=========j"+j); 9 } 10 } 11 } 12 class ExtendsThread extends Thread{ 13 @Override 14 public void run() { 15 for (int i = 65; i <91; i++) { 16 System.out.println((char)i); 17 } 18 } 19 }
执行结果:
可以看到两个线程在交替运行。
使用实现Runnable接口来开启多线程:代码示例:
1 package com.Allen.Thread; 2 3 public class Demo6 { 4 5 public static void main(String[] args) { 6 ImplementsRunnable ir=new ImplementsRunnable(); 7 Thread td=new Thread(ir); 8 td.start(); 9 for (int j = 0; j < 1000; j++) { 10 System.out.println("====j"+j); 11 } 12 } 13 } 14 class ImplementsRunnable implements Runnable{ 15 16 @Override 17 public void run() { 18 for (int i = 0; i < 1000; i++) { 19 20 System.out.println("***********i"+i); 21 } 22 } 23 }
执行结果:
实现Runnable接口来开启多线程还可以使用匿名对象 代码示例:
1 package com.Allen.Thread; 2 3 public class Demo6 { 4 5 public static void main(String[] args) { 6 7 Thread td=new Thread(new ImplementsRunnable()); //这里使用的是匿名对象 8 td.start(); 9 for (int j = 0; j < 1000; j++) { 10 System.out.println("====j"+j); 11 } 12 } 13 } 14 class ImplementsRunnable implements Runnable{ 15 16 @Override 17 public void run() { 18 for (int i = 0; i < 1000; i++) { 19 20 System.out.println("***********i"+i); 21 } 22 } 23 }
线程的执行原理:
线程的执行:CPU的抢占式的调度模式,抢占CPU的时间片
不同的线程不共享栈空间,需要开辟栈空间单独运行
线程的生命周期:
***1. 线程的生命周期 / 线程的状态
① 生命周期:从事物的出生,到消亡的过程。
***② 线程生命周期的状态:
1 》初始状态 : 创建了线程对象,但是没有调用 start 方法开启线程。
2 》可运行状态: 调用了 start 方法,到线程队列中排队,抢占 cpu 的时间片。但是还没有抢占上
。
3 》运行状态: 抢到了 cpu 的时间片。正在执行。
4 》 终止状态: cpu 时间片之内完成了线程的执行。
5 》 阻塞状态: cpu 时间片执行期间,遇到了意外的情况。
③ 线程的生命周期,指同一个线程在不同时期的状态。
④ java 中,线程的生命周期通过类来表示不同的状态 : Thread.State
new
至今尚未启动的线程处于这种状态。
runnable
正在 Java 虚拟机中执行的线程处于这种状态。
blocked
受阻塞并等待某个监视器锁的线程处于这种状态。
waiting
无限期地等待另一个线程来执行某一特定操作的线程处于这种状态。
timed_waiting
等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态。
terminated
已退出的线程处于这种状态。
线程的常用方法;
1.getName()返回线程的名称
2.currentThread()获取当前线程的引用对象。
线程的名称 main方法所在的线程为主线程 ,线程名为main
自定义的线程:Thread-0,Thread-1 默认格式:Thread-index 其中index从0开始 线程的名称可以设置
3.setName () 设置线程的名称
4.***getpriority()/setPriority() 返回线程的优先级/设置线程的优先级
***线程的优先级:从1到10,默认为5,最高优先级为10,最低优先级为1
线程如果优先级越高,抢占CPU时间片的可能性越大,默认一个线程创建时,优先级为5.
5.isDaemon()/setDeamon(true) 判断该线程是否为守护线程/设置线程为守护线程,参数值为true。
守护线程是用来守护用户线程,为用户线程进行准备或者守护的工作。
随着用户线程的消亡,守护线程无论是否执行完都会随着用户线程消亡。
6.join()等待该线程的终止,相当于用户调用。
7****sleep(ms) 休眠,毫秒值
8.start()开启线程的方法,会默认调用run()方法,进行线程的开启。
9.yield()退出当前正在执行的线程,让给其他线程执行,线程的让步。
守护线程的代码示例:
1 package com.Allen.Thread; 2 3 public class Demo7 { 4 5 public static void main(String[] args) { 6 DaemonThread dh=new DaemonThread(); 7 dh.setDaemon(true); 8 dh.start(); 9 for (int j = 0; j <20; j++) { 10 System.out.println("****"+j); 11 } 12 } 13 14 } 15 class DaemonThread extends Thread{ 16 @Override 17 public void run() { 18 for (int i = 0; i < 100; i++) { 19 20 System.out.println("=================="+i); 21 } 22 } 23 }
执行结果:
本例DaemonThread线程要打印倒99,但是随着主线程的消亡,守护线程也消亡了,但是为什么主线程 到19就消亡了,而守护线程却到了28呢?这是因为有延迟,不能立即结束。
主线程和守护线程的关系就像人与影子的关系,共存亡。
线程的安全问题:
1.多线程:多个线程并发执行。
2.多线程在执行时,会引发安全问题
3. 通过银行账户取款的模拟来演示多线程的安全问题。
4. 多线程的安全问题:
多个线程共同访问共享资源 ( 共有的资源 ) 时,由于线程的调度机制是抢占式调度,可能会发生多个线程在执行时,
同时操作共享资源,导致程序执行结果与预期不一致的现象。
5. 解决多线程的安全问题:
1> 解决方式一:同步:但是该方式会导致效率低,相当于单个线程执行。
a) 同步方式: ( 加锁 )
① 同步方法 : 相当于同步代码块中的 this 锁。
格式 :
权限修饰符 修饰符 synchronized 方法的返回值 方法的名称 ( 参数 )
② 同步代码块:
1 》 同步锁对象 :任意对象
格式 : synchronized ( 任意对象 ){
加锁的代码
}
2 》同步 this 锁:
③ 同步代码块和同步方法加锁时,需要注意:
《 1 》 加锁必须是给共享资源加的。
《 2 》 必须加的是同一把锁。
多线程安全问题的代码示例:
1 package com; 2 /** 3 1.多线程 : 多个线程并发执行。 4 2.多线程在执行时,会引发安全问题。 5 3.通过银行账户取款的模拟来演示多线程的安全问题。 6 4.多线程的安全问题: 7 多个线程共同访问共享资源(共有的资源)时,由于线程的调度机制是抢占式调度,可能会发生多个线程在执行时, 8 同时操作共享资源,导致程序执行结果与预期不一致的现象。 9 5.解决多线程的安全问题: 10 1>解决方式一:同步:但是该方式会导致效率低,相当于单个线程执行。 11 a)同步方式:(加锁) 12 ① 同步方法: 相当于同步代码块中的this锁。 13 格式 : 14 权限修饰符 修饰符 synchronized 方法的返回值 方法的名称(参数) 15 ② 同步代码块: 16 1》 同步锁对象 :任意对象 17 格式 :synchronized (任意对象){ 18 加锁的代码 19 } 20 2》同步this锁: 21 ③ 同步代码块和同步方法加锁时,需要注意: 22 《1》 加锁必须是给共享资源加的。 23 《2》 必须加的是同一把锁。 24 */ 25 public class 多线程的安全问题 { 26 public static void main(String[] args) { 27 Account a=new Account(); 28 //多线程 29 Thread t=new Thread(a); 30 Thread t1=new Thread(a); 31 t.setName("张三"); 32 t1.setName("李四"); 33 t.start(); 34 t1.start(); 35 } 36 } 37 class Account implements Runnable{ 38 double balance=1000;//账户余额 39 Object obj=new Object();//任意对象 40 String s=new String(); 41 //同步方法 42 @Override 43 public /*synchronized*/ void run() { 44 //同步锁对象,任意对象。 45 synchronized (this) {//this锁 46 //取款 47 if (balance > 0) { 48 //休眠 49 try { 50 Thread.sleep(1000); 51 } catch (InterruptedException e) { 52 // TODO Auto-generated catch block 53 e.printStackTrace(); 54 } 55 balance -= 1000; 56 System.out.println(Thread.currentThread().getName() + "取款后,金额为" + balance); 57 } else { 58 System.out.println(Thread.currentThread().getName() + "余额不足"); 59 } 60 } 61 } 62 }
======================================================================
1 package com; 2 /** 3 4 1.多线程的安全问题: ① 多个线程 ② 共享资源。 5 2.同步: 判断多个线程是否加的是同一把锁。 6 ① 同步方法 7 ② 同步代码块: 8 1》 锁对象(任意对象) 9 2》this锁 10 3》静态锁 (静态对象) 11 4》类锁(.class) 12 */ 13 public class 继承方式下的多线程的安全问题 { 14 public static void main(String[] args) { 15 AccountThread a=new AccountThread(); 16 AccountThread a1=new AccountThread(); 17 a.setName("张三"); 18 a1.setName("李四"); 19 a.start(); 20 a1.start(); 21 22 } 23 } 24 class AccountThread extends Thread{ 25 static double balance=1000;//账户余额 26 //静态锁 27 static Object o=new Object(); 28 //同步方法 29 @Override 30 public void run() { 31 //类锁 32 synchronized (AccountThread.class) {//this 33 //取款 34 if (balance > 0) { 35 //休眠 36 try { 37 Thread.sleep(1000); 38 } catch (InterruptedException e) { 39 // TODO Auto-generated catch block 40 e.printStackTrace(); 41 } 42 balance -= 1000; 43 System.out.println(Thread.currentThread().getName() + "取款后,金额为" + balance); 44 } else { 45 System.out.println(Thread.currentThread().getName() + "余额不足"); 46 } 47 } 48 } 49 }
PS:alt+方向键可以上下平移代码
ctrl+加减号可以调节eclipse的字体大小
shift+ctrl+delete 删除整行
1 package com.Allen.Thread; 2 public class Demo8 { 3 public static void main(String[] args) { 4 CountMoney td1=new CountMoney(); 5 CountMoney td2=new CountMoney(); 6 td1.setName("张先生"); 7 td2.setName("李先生"); 8 td1.start(); 9 td2.start(); 10 } 11 } 12 class CountMoney extends Thread{ 13 static double count=1000; 14 static Object o=new Object(); 15 public void run() { 16 synchronized(o) { 17 if(count>0) { 18 try { 19 Thread.sleep(1000); 20 } catch (InterruptedException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 } 24 count-=1000; 25 System.out.println(Thread.currentThread().getName()+"取款成功,余额:"+count); 26 }else { 27 System.out.println(Thread.currentThread().getName()+"余额不足"); 28 } 29 } 30 } 31 32 }
转载于:https://www.cnblogs.com/ywzbky/p/10719721.html
JAVA中多线程基础知识相关推荐
- 第76节:Java中的基础知识
第76节:Java中的基础知识 设置环境,安装操作系统,安装备份,就是镜像,jdk配置环境,eclipse下载解压即可使用,下载tomcat 折佣动态代理解决网站的字符集编码问题 使用request. ...
- Java程序设计 多线程 基础知识题
2-1 以下哪个方法用于定义线程的执行体? ( ) (1分) A. start() B. init() C. run() D. ynchronized() 2-2 以下哪个关键字可以用来为对象加互斥锁 ...
- Java中整数基础知识
最近做了一道题,非常有意思,题本身很简单,但涉及到整数的最大值以及最小值,当写测试用例的时候,却犯了一个错误,发现最小整数并不是0xFFFFFFFF,我们来仔细看一下. 整数基础 Java中,整数都是 ...
- java中计算机基础知识_整理一些计算机基础知识!
为了使不同计算机厂家生产的计算机能够相互通信,以便在更大的范围内建立计算机网络,国际标准化组织(ISO)在1978年提出了"开放系统互联参考模型",即著名的OSI/RM模型(Ope ...
- Java这些多线程基础知识你会吗?
0.并发和并行.进程核线程.多进程和多线程的区别: (这里的时间和时刻上的概念同物理上的一样) 并发:在一段时间内多个任务同时执行,或者说是在一段很短的时间内可以执行多条程序指令,微观上看起来好像是可 ...
- Java多线程基础知识
多线程基础知识 这是我再次学习多线程知识的一个总结,对于刚刚接触的学习者是比较友好易懂的,便于快速的理解和掌握. 一.基本概念: 1.进程:进程就是运行中的程序,当一个程序开始执行,操作系统就会给这个 ...
- java 网络爬虫 正则表达式_【干货】Java网络爬虫基础知识
原标题:[干货]Java网络爬虫基础知识 引言 Java 网络爬虫具有很好的扩展性可伸缩性,其是目前搜索引擎开发的重要组成部分.例如,著名的网络爬虫工具 Nutch 便是采用 Java 开发,该工具以 ...
- java的一些基础知识(引用BlogJava 落花飞雪)
java的一些基础知识(引用BlogJava 落花飞雪) <Practical Java>笔记 1. 声明是什么? String s = "Hello world!" ...
- java to go 基础知识与区别入土指南
java to go 基础知识与区别入土指南 文章目录 java to go 基础知识与区别入土指南 @[toc] 基础篇 关于基础类型 关于复合数据类型 关于切片 关于Map 关于sync.map ...
最新文章
- zookeeper集群环境搭建
- 自动化html定位,Selenium自动化定位方法
- 标准梯度—lhMorpGradient
- 【Python爬虫】BeautifulSoup4 库的一些用法
- sqlserver 2008修改数据库表的时候错误提示“阻止保存要求重新创建表的更改”...
- python 的异常及其处理
- git status命令
- C. Tourist Problem
- python小白逆袭大佬_Python小白逆袭大神心得
- 阿里巴巴2021年java研发工程师暑期实习一面及二面面经
- OC算法 输出手机号码归属地
- 微星性能测试软件,MSI Kombustor
- 漫谈程序员(十)大白菜装机版安装win7系统使用教程
- 电脑软件测试英雄联盟,lol电脑配置检测,如何测试自己的网络玩lol的具体情况?...
- 29岁vivo员工吐槽:整理出这份8万字Java性能优化实战解析
- 研究生被导师嫌弃是种怎样的体验?写的太真实了...
- text-decoration 属性的简单介绍
- 几种部署工具比较foreman, ansible, fuel
- [Docker]docker: invalid reference format: repository name must be lowercase.
- 哈勃经典照片:数百万恒星构成宇宙喷泉(一)(图)
热门文章
- 利润太薄甚至亏损?小米卢伟冰解释红米Note7线下缺货问题
- QT4.8.5 显示中文
- 基于Linux和MiniGUI的嵌入式系统软件开发指南(六)
- java加密 c解密_java+加密解密
- 小帅小胖智能机器人如何使用_小帅智能教育机器人使用技巧篇(下篇)
- java context.xml_java-context.xml的解释
- 一台新云主机nodejs项目部署过程
- 固态和机械硬盘组raid_电脑是固态硬盘好还是机械硬盘
- 【java】java 定时任务线程池 ScheduledThreadPoolExecutor 源码阅读
- 【Flink】Flink 实现 AT_LEAST_ONCE EXACTLY_ONCE 案例