asp.net+Android+IOS开发 、Net培训、期待与您交流!
(前言:本篇文章主要依据毕向东老师的课程视频整理而成,如要详细学习,请观看毕老师视频 百度网盘链接地址: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...........
ASP.Net+Android+IOS开发 、Net培训、期待与您交流!
新闻热点
疑难解答