多线程(下)
来源:互联网 发布:unity3d 模型导出插件 编辑:程序博客网 时间:2024/06/10 04:59
线程的状态
- 新生状态 : 用new关键字创建一个线程,该线程就处于新建状态
- 就绪状态 : 调用start()方法后线程处于就绪状态,具备了运行的条件,但是没有分配到CPU,处于线程的就绪状态
- 运行状态 : 处于就绪状态的线程获得了CPU的执行权,开始执行run方法中的线程执行体,该线程就处于运行状态。
- 阻塞状态
- 1.当线程调用了一个阻塞式的IO方法时,该线程就会进入阻塞状态。
- 2.当线程调用了某个对象的wait()方法时,也会进入阻塞状态,如果想进入就绪状态就会需要调用notify()或者notifyAll()方法唤醒线程
- 3.当线程调用Thread的sleep()方法时,也会进入阻塞状态。
- 4.当一个线程调用了另一个线程的join()方法,也会进入阻塞状态,这种情况下,需要等待新加入的线程运行结束后才会结束阻塞状态,进入就绪状态
- 死亡状态 : 线程的run()方法执行完毕或者抛出一个未捕获的异常、错误,线程就会进入死亡状态。
线程的优先级
- 线程的优先级用1-10之间的整数表示,数字越大优先级越高。
- 调用Thread类中getPriority()查看线程的优先级。线程默认优先级是5
- 调用Thread类中setPriority()方法修改线程的优先级
线程让步
使用yield()方法实现。这个方法和sleep方法类似,都可以让当前的线程暂停。区别在于yield()方法不会阻塞该线程,只是将线程转换为就绪状态。当某个线程调用yield()方法之后,只有与当前线程优先级相同的或者更高的线程才能获得执行的机会。
public class ThreadDemo extends Thread{ public ThreadDemo(String name) { super(name);//调用父类的构造方法 } @Override public void run() { for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+"---"+i); if(i==3){ System.out.println("线程让步"); Thread.yield(); //线程运行到这里,开始做出让步 } } }}public static void main(String[] args) {ThreadDemo t1=new ThreadDemo("线程一");ThreadDemo t2=new ThreadDemo("线程二");t1.start();t2.start();}
运行结果:
线程插队
- 调用join()方法实现线程插队功能
调用join()方法后,线程会处于阻塞状态,直到被join方法加入的线程执行完它才会继续执行。
public class ThreadDemo implements Runnable {@Overridepublic void run() { for (int i = 0; i < 6; i++) { System.out.println(Thread.currentThread().getName() + "输入" + i); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}}public static void main(String[] args) {ThreadDemo threadDemo = new ThreadDemo();Thread t1 = new Thread(threadDemo);t1.start();for (int i = 1; i < 6; i++) { System.out.println(Thread.currentThread().getName() + "输入" + i); if (i == 2) { try { t1.join(); // 调用join方法 Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}}
运行结果:
- 从运行结果可以看出,当main线程中的循环变量执行到2时,调用t1线程的join方法,这时t1线程就会插队优先执行,直到t1线程执行完毕,main线程才开始继续执行。
多线程通信问题的解决
假设这样一个场景,一个生产车间,生产一瓶哇哈哈,然后销售一瓶哇哈哈。下面我们来模拟这个过程。
商品类
-
public class Commodity {
private String name; //商品名称
private int num; //商品数量
/**
* 销售
* @return
*/
public synchronized String market(){
System.out.println(“销售第”+num+”瓶”+name);
return name+num;
}
public synchronized void production(String name,int num){
this.name=name;
this.num=num;
System.out.println(“生产第”+num+”瓶——–>”+name);
}
} 工厂类
public class Producer implements Runnable{ Commodity commodity; public Producer(Commodity commodity) { // TODO Auto-generated constructor stub this.commodity=commodity; } @Override public void run() { // TODO Auto-generated method stub int num=1; while(true){ commodity.production("哇哈哈", num++); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}
销售类
public class Market implements Runnable{ Commodity commodity; public Market(Commodity commodity) { this.commodity=commodity; } @Override public void run() { while(true){ commodity.market(); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}
*测试类
public class Test {public static void main(String[] args) { Commodity commodity=new Commodity(); Producer p=new Producer(commodity); Market m=new Market(commodity); Thread t1=new Thread(p,"生产"); Thread t2=new Thread(m,"销售"); t1.start(); t2.start();}}
- 运行结果:
- 从上面的运行结果可以看出,第5瓶饮料生产完后,第5瓶哇哈哈被销售了两次,显然不符合常理。这时候我们就需要使用Object类中提供的wait()、notify()、notifyAll()方法来解决线程间的通信问题。
首先介绍这几个方法的作用
- void wait() 使当前线程放弃同步锁并进入等待,直到其他线程进入此同步锁,并调用notify()方法或notifyAll()方法唤醒该线程。
- void notify() 唤醒此同步锁上等待的第一个调用wait()方法的线程
- void notifyAll() 唤醒此同步锁上调用wait()方法的所有线程。
接下来我们来完善上面的程序
- 商品类
public class Commodity { private String name; //商品名称 private int num; //商品数量 private boolean flag=false; /** * 销售 * @return */ public synchronized String market(){ if(!flag){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("销售第"+num+"瓶"+name); flag=false; notify(); return name+num; } public synchronized void production(String name,int num){ if(flag){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("生产第"+num+"瓶-------->"+name); this.name=name; this.num=num; flag=true; notify(); } }
工厂类
public class Producer implements Runnable{Commodity commodity;public Producer(Commodity commodity) { // TODO Auto-generated constructor stub this.commodity=commodity;}@Override public void run() { // TODO Auto-generated method stub int num=1; while(true){ commodity.production("哇哈哈", num++); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}}
销售类
public class Market implements Runnable{Commodity commodity;public Market(Commodity commodity) { this.commodity=commodity;}@Overridepublic void run() { while(true){ commodity.market(); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}}
测试类
public class Test {public static void main(String[] args) { Commodity commodity=new Commodity(); Producer p=new Producer(commodity); Market m=new Market(commodity); Thread t1=new Thread(p,"生产"); Thread t2=new Thread(m,"销售"); t1.start(); t2.start();}}
- 运行结果:
- 现在的运行结果就合理了,生产一瓶销售一瓶。
阅读全文
0 0
- Java-----多线程(下)
- Java多线程(下)
- Java 多线程(下)
- Java_多线程(下)
- 多线程开发(下)
- java多线程(下)
- 多线程(下)
- 多线程(下)
- 多线程编程笔记(下)
- Linux 下多线程(二)
- Linux 下多线程(三)
- 黑马程序员-多线程(下)
- 多线程下载-下(断点)
- iOS多线程--下(GCD)
- 多线程之CompletableFuture(下)
- windows下C++多线程学习之一(多线程基础)
- Linux下的多线程编程(转)
- linux下实现多线程同步(一)
- rgba()和opacity的透明效果有什么不同?
- codeforces 459A
- 免费赚取比特币
- java创建对象的四种方式
- mysql5.7安装步奏
- 多线程(下)
- 错误提示信息汇总
- spring+maven+log4j2 配置
- POJ 2502 Subway 笔记
- 《深度学习原理与TensorFlow实践》学习笔记(二)
- 深copy和浅copy
- 正则表达式
- Markdown进阶:序列图
- 微信开发交互返回当前时间的说明