Java多线程基础(二)
来源:互联网 发布:淘宝联盟用了红包丢单 编辑:程序博客网 时间:2024/05/20 16:35
Java多线程理解
一、常用方法
1、join()方法,让一个线程等待另一个线程执行完之后再执行。例如:A线程执行体中执行B线程的join方法,那么需要等到B线程执行完毕之后再执行A线程。
示例:
public class MyRunnable implements Runnable{private boolean flag = false;@Overridepublic void run() {for(int i = 0 ; i < 100 && !flag ; i++){System.out.println(Thread.currentThread().getName()+"---"+i);}}}
public class Test extends Thread{public static void main(String[] args) throws InterruptedException, ExecutionException {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);for(int i = 0 ; i < 100 ; i++){System.out.println(Thread.currentThread().getName()+"--"+i);if(i == 30){thread.start();thread.join();}}}}当i== 30时,在主线程中插入thread线程,直到thread线程执行完毕,主线程才开始执行。
2、sleep():让线程暂停执行指定的时间。由于线程不是出于就绪状态,在指定时间之内,线程不能执行。特殊应用:当new一个线程并调用start()方法之后,线程需要等待某个时间获取CPU时间片才能执行,如果希望这个线程立即执行,可以使用sleep(1),当然这个立即执行的线程不一定是多线程中的哪一个。
public class Test extends Thread{public static void main(String[] args) throws InterruptedException, ExecutionException {MyRunnable myRunnable = new MyRunnable();Thread thread1 = new Thread(myRunnable);thread1.setName("A");Thread thread2 = new Thread(myRunnable);thread2.setName("B");Thread thread3 = new Thread(myRunnable);thread3.setName("C");for(int i = 0 ; i < 100 ; i++){System.out.println(Thread.currentThread().getName()+"---"+i);if(i==30){thread1.start();Thread.sleep(1);}if(i==40){thread2.start();Thread.sleep(1);}if(i==50){thread3.start();Thread.sleep(1);}}}}
class MyRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } }}
3、后台线程
概念/目的:后台线程主要是为其他线程(相对可以称之为前台线程)提供服务,或“守护线程”。如JVM中的垃圾回收线程。
生命周期:后台线程的生命周期与前台线程生命周期有一定关联。主要体现在:当所有的前台线程都进入死亡状态时,后台线程会自动死亡(其实这个也很好理解,因为后台线程存在的目的在于为前台线程服务的,既然所有的前台线程都死亡了,那它自己还留着有什么用...伟大啊 ! !)。
设置后台线程:调用Thread对象的setDaemon(true)方法可以将指定的线程设置为后台线程。
判断线程是否是后台线程:调用thread对象的isDeamon()方法。
注:main线程默认是前台线程,前台线程创建中创建的子线程默认是前台线程,后台线程中创建的线程默认是后台线程。调用setDeamon(true)方法将前台线程设置为后台线程时,需要在start()方法调用之前。前天线程都死亡后,JVM通知后台线程死亡,但从接收指令到作出响应,需要一定的时间。public class Test extends Thread{public static void main(String[] args) throws InterruptedException, ExecutionException {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);for(int i = 0 ; i < 10 ; i++){System.out.println(Thread.currentThread().getName()+"--"+i);if(i == 3){thread.setDaemon(true);thread.start();}}}}
public class MyRunnable implements Runnable{private boolean flag = false;@Overridepublic void run() {for(int i = 0 ; i < 10000 && !flag ; i++){System.out.println(Thread.currentThread().getName()+"---"+i);}}public void stoped(){this.flag = true;}}执行结果:
main--0main--1main--2main--3main--4main--5main--6main--7main--8main--9Thread-0---0Thread-0---1Thread-0---2Thread-0---3Thread-0---4Thread-0---5Thread-0---6Thread-0---7Thread-0---8Thread-0---94、常用的快速终止线程的方法
一般线程状态分成就绪状态、运行状态、死亡状态。
就绪状态转换成运行状态:线程得到处理器资源
运行状态转换成就绪窗台:此线程主动执行yeild()方法或者再运行过程中失去处理器资源。
运行状态转成死亡状态: 线程执行体执行结束或者发生了异常。
此处需要特别注意的是:当调用线程的yield()方法时,线程从运行状态转换为就绪状态,但接下来CPU调度就绪状态中的哪个线程具有一定的随机性,因此,可能会出现A线程调用了yield()方法后,接下来CPU仍然调度了A线程的情况。
由于实际的业务需要,常常会遇到需要在特定时机终止某一线程的运行,使其进入到死亡状态。目前最通用的做法是设置一boolean型的变量,当条件满足时,使线程执行体快速执行完毕。如:
public class MyRunnable implements Runnable{private boolean flag = false;@Overridepublic void run() {for(int i = 0 ; i < 10000 && !flag ; i++){System.out.println(Thread.currentThread().getName()+"---"+i);}}public void stoped(){this.flag = true;}}
public class Test extends Thread{public static void main(String[] args) throws InterruptedException, ExecutionException {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);for(int i = 0 ; i < 10000000 ; i++){if(i==3){thread.start();}if(i == 400000){myRunnable.stoped();}}}}二、对象及变量的并发访问
1、(1)方法内变量是线程安全的
public class SelfNum {public void addI(String name){int num = 0;if("a".equals(name)){num = 100;System.out.println(ThreadA.currentThread().getName()+",a set over");try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if("b".equals(name)){num = 200;System.out.println(ThreadA.currentThread().getName()+",b set over");try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println(ThreadA.currentThread().getName()+",当前num值是:"+num);}}
(2)实例变量非线程安全public class SelfNum {private int num = 0;public void addI(String name){if("a".equals(name)){num = 100;System.out.println(ThreadA.currentThread().getName()+",a set over");try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if("b".equals(name)){num = 200;System.out.println(ThreadA.currentThread().getName()+",b set over");try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println(ThreadA.currentThread().getName()+",当前num值是:"+num);}}
测试:public class MainTest {public static void main(String[] args) {SelfNum selfNum = new SelfNum();ThreadA threadA = new ThreadA(selfNum);ThreadB threadB = new ThreadB(selfNum);threadA.start();threadB.start();}}第一种情况结果:
Thread-0,a set overThread-1,b set overThread-1,当前num值是:200Thread-0,当前num值是:100
第二种情况结果:
Thread-0,a set overThread-1,b set overThread-0,当前num值是:200Thread-1,当前num值是:200
- JAVA多线程基础(二)
- java多线程基础(二)
- Java多线程基础(二)
- JAVA多线程基础(二)
- java基础----多线程(二)
- java多线程基础二
- java多线程基础二
- java多线程编程 - 基础篇 (二)
- 黑马程序员 JAVA基础--多线程(二)
- Java基础—多线程(二)
- 黑马程序员--Java基础--多线程(二)
- java基础的核心技术:多线程(二)
- java多线程_基础(二)
- 多线程基础(二)
- Java基础之(三十七)Java多线程编程<二>
- java多线程并发(二)(线程基础)
- 黑马程序员——JAVA基础----多线程(二)
- JAVA进阶学习-多线程基础详解(二)-同步
- RecycleView.Adapter的适配方法
- UML建模
- PAT 1013 乙等(数素数)c++
- 文章标题
- 反向传播(BPTT)与循环神经网络(RNN)文本预测
- Java多线程基础(二)
- 寻觅web项目的lib下为什么会有weblogic.jar
- P1424小鱼的航程
- COJ-1005-Binary Search Tree analog
- kafka教程-基本概念
- HDU
- Java三大框架搭建
- boost库简单读写xml
- 山东省第八届ACM省赛 J 题(company)