(前言:本篇文章主要依据毕向东老师的课程视频整理而成,如要详细学习,请观看毕老师视频 百度网盘链接地址:http://pan.baidu.com/s/1i3m6DrJ)
目录:1、线程通信--生产消费者示例(线程通信安全、等待唤醒机制) 2、停止线程、及其会出现的问题、及解决的办法 3、守护线程及几个Thread的方法 4、工作中线程的常见写法
1、线程通信--生产消费者示例
代码示例:
public class ProducerConsumer { //需求:生产和消费行为依次进行。 设置产品为BMW 设置生产者和消费者线程各两个 public static void main(String[] args) { Product pro=new Product(); new Thread(new Producter(pro)).start(); new Thread(new Consumer(pro)).start(); new Thread(new Producter(pro)).start(); new Thread(new Consumer(pro)).start(); } } class Product{ private String name; private int No=1; boolean flag=false; public synchronized void set(String names){ while(flag) try { this.wait();//等待状态 } catch (InterruptedException e) { e.printStackTrace(); } this.name=names+"---"+this.No++; System.out.println(this.name+"---被"+Thread.currentThread().getName()+"生产"); flag=true; this.notifyAll();//唤醒所有线程 } public synchronized void out(){ while(!flag) try { this.wait();//等待状态 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.name+"---被"+Thread.currentThread().getName()+"消费了-------"); flag=false; this.notifyAll();//唤醒所有线程 } } //生产者 class Producter implements Runnable{ private Product p; public Producter(Product pr){ this.p=pr; } public void run(){ while(true){ p.set("BMW"); } } } //消费者 class Consumer implements Runnable{ private Product p; public Consumer(Product pr){ this.p=pr; } public void run(){ while(true){ p.out(); } } }
使用JDK5.0新特性改进后的代码
1 /*JDK5.0后增加了Lock 和Condition新类特性来取代 同步和锁的繁琐操作 */ 2 public class ProducerConsumerNew { 3 4 public static void main(String[] args) { 5 6 Product pro=new Product(); 7 8 new Thread(new Producter(pro)).start(); 9 new Thread(new Consumer(pro)).start(); 10 new Thread(new Producter(pro)).start(); 11 new Thread(new Consumer(pro)).start(); 12 13 } 14 15 } 16 class ProductNew{ 17 private String name; 18 private int No=1; 19 boolean flag=false; 20 21 private Lock lock=new ReentrantLock(); 22 private Condition con1=lock.newCondition(); 23 private Condition con2=lock.newCondition(); 24 25 public void set(String name){ 26 27 while(flag) 28 try { 29 lock.lock(); 30 con1.wait(); 31 } catch (InterruptedException e) { 32 e.printStackTrace(); 33 }finally{ 34 lock.unlock(); 35 } 36 this.name=name+"---"+this.No++; 37 System.out.println(this.name+"---被"+Thread.currentThread().getName()+"生产"); 38 39 this.flag=true; 40 con2.signal(); 41 } 42 43 public void out(){ 44 while(!this.flag) 45 try { 46 lock.lock(); 47 con2.wait(); 48 } catch (InterruptedException e) { 49 e.printStackTrace(); 50 }finally{ 51 lock.unlock(); 52 con1.signal(); 53 } 54 System.out.println(this.name+"---被"+Thread.currentThread().getName()+"消费了-------"); 55 56 this.flag=false; 57 } 58 } 59 //生产者 60 class ProducterNew implements Runnable{ 61 private ProductNew p; 62 public ProducterNew(ProductNew pr){ 63 this.p=pr; 64 } 65 public void run(){ 66 while(true){ 67 p.set("BMW"); 68 } 69 } 70 } 71 //消费者 72 class ConsumerNew implements Runnable{ 73 private ProductNew p; 74 public ConsumerNew(ProductNew pr){ 75 this.p=pr; 76 } 77 public void run(){ 78 while(true) 79 p.out(); 80 } 81 }
2、停止线程、及其会出现的问题、及解决的办法
停止线程思路:开启多线程运行,运行代码通常是循环结构,只要控制住循环,就可以让run()方法结束,线程即结束。
特殊情况:当线程处于冻结状态(wait()),就不会读取到标记,那么线程就不会结束。
解决办法:当没有指定的方式让冻结的线程恢复到运行状态时,需要用Interrupt()方法强制清除冻结状态,再用操作标记让线程结束
一个简单的代码例子
1 public class ThreadStop { 2 3 public static void main(String[] args) { 4 5 ThreadTt tt=new ThreadTt(); 6 7 Thread th1=new Thread(tt); 8 Thread th2=new Thread(tt); 9 th1.start(); 10 th2.start(); 11 int count=0; 12 while(true){ 13 if(++count>60){ //循环来控制线程的结束 14 th1.interrupt(); //强制清除线程冻结状态 15 th2.interrupt(); 16 break; 17 } 18 System.out.println(Thread.currentThread().getName()+"....run---"+count); 19 } 20 System.out.println(Thread.currentThread().getName()+"....over"); 21 } 22 } 23 class ThreadTt implements Runnable{ 24 25 boolean flag=true; 26 Lock lock=new ReentrantLock(); 27 Condition con=lock.newCondition(); 28 public synchronized void run() { 29 30 while(flag){ 31 try { 32 wait(); //用这个方法让线程处于冻结状态 33 } catch (InterruptedException e) { 34 System.out.println(e.getStackTrace()); 35 flag=false; 36 } 37 System.out.println(Thread.currentThread().getName()+"...run"); 38 } 39 } 40 }
3、守护线程及几个Thread的方法
守护线程/用户线程:通俗而言为”后台进程”,当前台进程都结束时,后台进程自动结束;当正在运行的线程都是守护线程时,JVM自动退出。
setDaemon()方法设置守护线程,该方法必须在启动线程前调用
Join()方法 特点:当A线程执行到了B线程的jion()方法是,A就会等待,等B线程都执行完以后,A才会执行。Jion可以用来临时加入线程执行 线程抢夺cpu执行权
ToString()方法
setPriority()方法 更改线程的优先级,优先级代表抢夺资源的频率高低
Yield()方法 暂停当前线程的执行,去执行其它线程
4、工作中线程的常见写法(用到内部类)
不多说,看代码
1 public class ThreadStand { 2 3 public static void main(String[] args) { 4 //工作中多线程的常见写法,构建内部类 5 new Thread(){ 6 public void run(){ 7 for(int i=0;i<100;i++) 8 System.out.println(Thread.currentThread().getName()+"....run...."+i); 9 } 10 }.start(); 11 12 for(int i=0;i<100;i++) 13 System.out.println(Thread.currentThread().getName()+"....run...."+i); 14 15 //构造内部类 16 Runnable rn= new Runnable(){ 17 public void run() { 18 for(int i=0;i<100;i++) 19 System.out.println(Thread.currentThread().getName()+"....run...."+i); 20 } 21 }; 22 new Thread(rn).start(); 23 } 24 }
初学者难免错误,欢迎评判指教,持续更正ing...........