多线程访问共同资源(队列,多线程,锁机制)
模拟场景:main方法为网络请求线程(也叫生产者线程),在网络请求线程中开启四个线程(消费者线程),进行高效处理队列中的共同资源(生产者线程生产的共同资源),等待资源处理完毕,网络请求线程执行结束,响应客户端。
消费者线程的线程体
1 import java.text.SimpleDateFormat; 2 import java.util.Date; 3 import java.util.concurrent.BlockingQueue; 4 import java.util.concurrent.LinkedBlockingQueue; 5 import java.util.concurrent.TimeUnit; 6 7 /** 8 * 【1】实现Runnable接口,重写run方法。 9 * 【2】run方法内的逻辑代码就是线程体 10 * 【3】创建线程类的对象 11 * 【4】创建线程类的代理对象 12 * 【5】代理对象调用start(),启动线程 13 * @author it-c-1201 14 * 15 */ 16 public class MyThread implements Runnable{ 17 //多线程访问共同资源的队列 18 private BlockingQueue<String> a = new LinkedBlockingQueue<String>(); 19 20 //队列中共同资源的个数 21 private Integer count=0; 22 23 //线程锁 24 private Object object=new Object(); 25 26 //生产者生产完成标示<false 未生产完成,true 生产完成> 27 private boolean flag=false; 28 29 //线程类构造器。 30 public MyThread(BlockingQueue<String> a){ 31 this.a=a; 32 } 33 34 //获取线程锁对象 35 public Object getObjectByLock(){ 36 return this.object; 37 } 38 39 //标志生产者生产结束 40 public void setFlag(){ 41 this.flag=true; 42 } 43 44 //队列数据加一个 45 public void setCount(){ 46 //当出现队列数据小于1的情况,恢复队列中数据个数为0 47 if(count<0){ 48 count=0; 49 } 50 count++; 51 } 52 53 //线程体 54 public void run() { 55 //消费 56 while(true){ 57 //获取当前线程名字 58 String threadName=Thread.currentThread().getName(); 59 60 //资源处理完毕&&生产者停止生产,则跳出死循环 61 if(count==0&&flag){ 62 break; 63 } 64 65 66 String pollInteger; 67 try { 68 //从队列中获取数据。如果没有数据等待100毫秒,100毫秒后还是无数据,返回null 69 pollInteger = a.poll(100, TimeUnit.MILLISECONDS); 70 71 //如果取出的数据为空,则暂停本次循环,进行下次循环(后边代码不执行) 72 if(pollInteger==null){ 73 continue; 74 } 75 76 //如果队列中资源个数为0,则暂停本次循环,进行下次循环 77 if(count==0||count<0){ 78 continue; 79 } 80 81 //说明从队列中取出数据,队列中数据个数减一 82 count--; 83 84 //获取执行时间点 85 SimpleDateFormat aDateFormat=new SimpleDateFormat("HH:mm:ss SS"); 86 Date date=new Date(); 87 String dateString=aDateFormat.format(date); 88 //模拟消费队列中获取的数据 89 System.out.println("MyThread.run(-->)"+threadName+"【"+pollInteger+"】 时间: "+dateString); 90 } catch (InterruptedException e) { 91 // TODO Auto-generated catch block 92 e.printStackTrace(); 93 } 94 95 } 96 97 //唤醒所有线程 98 synchronized(object){ 99 //唤醒该锁锁住的所有线程【证明没有数据要处理了,main方法中挂起的线程(模拟的网络请求线程)被唤醒,main方法执行结束】 100 object.notifyAll(); 101 String tString=Thread.currentThread().getName(); 102 System.out.println("MyThread.run(-->)"+tString+"notfyAll()"); 103 } 104 105 } 106 107 108 }
main方法(模拟的网络请求线程)
1 import java.text.SimpleDateFormat; 2 import java.util.Date; 3 import java.util.concurrent.BlockingQueue; 4 import java.util.concurrent.LinkedBlockingQueue; 5 6 7 public class Test { 8 9 //模拟多线程消费的共同资源 10 private static BlockingQueue<String> a = new LinkedBlockingQueue<String>(); 11 12 //模拟的网络请求来要执行的方法 13 public static void main(String[] args) { 14 //新建线程对象 15 MyThread myThread=new MyThread(a); 16 17 18 //开启四个消费线程 19 for(int i=0;i<4;i++){ 20 Thread aThread=new Thread(myThread); 21 aThread.setName("THREAD"+i); 22 aThread.start(); 23 } 24 25 //模拟生产线程 26 try { 27 for(int i=0;i<100;i++){ 28 //往队列中加数据 29 a.put(i+"sxf"); 30 //队列中数据个数加1 31 myThread.setCount(); 32 } 33 } catch (InterruptedException e) { 34 // TODO Auto-generated catch block 35 e.printStackTrace(); 36 }finally{ 37 myThread.setFlag(); 38 } 39 40 41 42 //模拟当生产完毕后,网络请求线程也叫生产线程被阻塞 43 synchronized (myThread.getObjectByLock()) { 44 try { 45 myThread.getObjectByLock().wait(); 46 } catch (InterruptedException e) { 47 // TODO Auto-generated catch block 48 e.printStackTrace(); 49 } 50 } 51 52 //模拟网络请求线程被唤醒后,执行完毕,向客户端响应数据 53 SimpleDateFormat aDateFormat=new SimpleDateFormat("HH:mm:ss SS"); 54 Date date=new Date(); 55 String dateString=aDateFormat.format(date); 56 System.out.println("Test.main(完成时间:)"+dateString); 57 } 58 }
测试结果
1 MyThread.run(-->)THREAD2【2sxf】 时间: 19:39:06 127 2 MyThread.run(-->)THREAD3【0sxf】 时间: 19:39:06 127 3 MyThread.run(-->)THREAD0【1sxf】 时间: 19:39:06 127 4 MyThread.run(-->)THREAD2【4sxf】 时间: 19:39:06 128 5 MyThread.run(-->)THREAD0【6sxf】 时间: 19:39:06 128 6 MyThread.run(-->)THREAD1【3sxf】 时间: 19:39:06 127 7 MyThread.run(-->)THREAD2【7sxf】 时间: 19:39:06 128 8 MyThread.run(-->)THREAD0【8sxf】 时间: 19:39:06 128 9 MyThread.run(-->)THREAD3【5sxf】 时间: 19:39:06 128 10 MyThread.run(-->)THREAD2【10sxf】 时间: 19:39:06 128 11 MyThread.run(-->)THREAD3【12sxf】 时间: 19:39:06 129 12 MyThread.run(-->)THREAD1【9sxf】 时间: 19:39:06 128 13 MyThread.run(-->)THREAD3【14sxf】 时间: 19:39:06 129 14 MyThread.run(-->)THREAD1【15sxf】 时间: 19:39:06 129 15 MyThread.run(-->)THREAD3【16sxf】 时间: 19:39:06 129 16 MyThread.run(-->)THREAD2【13sxf】 时间: 19:39:06 129 17 MyThread.run(-->)THREAD0【11sxf】 时间: 19:39:06 129 18 MyThread.run(-->)THREAD3【18sxf】 时间: 19:39:06 129 19 MyThread.run(-->)THREAD2【19sxf】 时间: 19:39:06 129 20 MyThread.run(-->)THREAD0【20sxf】 时间: 19:39:06 129 21 MyThread.run(-->)THREAD3【21sxf】 时间: 19:39:06 129 22 MyThread.run(-->)THREAD2【22sxf】 时间: 19:39:06 129 23 MyThread.run(-->)THREAD1【17sxf】 时间: 19:39:06 129 24 MyThread.run(-->)THREAD3【24sxf】 时间: 19:39:06 129 25 MyThread.run(-->)THREAD0【23sxf】 时间: 19:39:06 129 26 MyThread.run(-->)THREAD2【25sxf】 时间: 19:39:06 129 27 MyThread.run(-->)THREAD1【26sxf】 时间: 19:39:06 129 28 MyThread.run(-->)THREAD2【29sxf】 时间: 19:39:06 129 29 MyThread.run(-->)THREAD0【28sxf】 时间: 19:39:06 129 30 MyThread.run(-->)THREAD3【27sxf】 时间: 19:39:06 129 31 MyThread.run(-->)THREAD1【30sxf】 时间: 19:39:06 129 32 MyThread.run(-->)THREAD2【31sxf】 时间: 19:39:06 130 33 MyThread.run(-->)THREAD0【32sxf】 时间: 19:39:06 130 34 MyThread.run(-->)THREAD3【33sxf】 时间: 19:39:06 130 35 MyThread.run(-->)THREAD1【34sxf】 时间: 19:39:06 130 36 MyThread.run(-->)THREAD2【35sxf】 时间: 19:39:06 130 37 MyThread.run(-->)THREAD0【36sxf】 时间: 19:39:06 130 38 MyThread.run(-->)THREAD3【37sxf】 时间: 19:39:06 130 39 MyThread.run(-->)THREAD1【38sxf】 时间: 19:39:06 130 40 MyThread.run(-->)THREAD2【39sxf】 时间: 19:39:06 130 41 MyThread.run(-->)THREAD0【40sxf】 时间: 19:39:06 130 42 MyThread.run(-->)THREAD3【41sxf】 时间: 19:39:06 130 43 MyThread.run(-->)THREAD1【42sxf】 时间: 19:39:06 130 44 MyThread.run(-->)THREAD2【43sxf】 时间: 19:39:06 130 45 MyThread.run(-->)THREAD0【44sxf】 时间: 19:39:06 130 46 MyThread.run(-->)THREAD3【45sxf】 时间: 19:39:06 130 47 MyThread.run(-->)THREAD1【46sxf】 时间: 19:39:06 130 48 MyThread.run(-->)THREAD2【47sxf】 时间: 19:39:06 130 49 MyThread.run(-->)THREAD0【48sxf】 时间: 19:39:06 130 50 MyThread.run(-->)THREAD3【49sxf】 时间: 19:39:06 130 51 MyThread.run(-->)THREAD1【50sxf】 时间: 19:39:06 130 52 MyThread.run(-->)THREAD2【51sxf】 时间: 19:39:06 130 53 MyThread.run(-->)THREAD0【52sxf】 时间: 19:39:06 130 54 MyThread.run(-->)THREAD3【53sxf】 时间: 19:39:06 130 55 MyThread.run(-->)THREAD1【54sxf】 时间: 19:39:06 130 56 MyThread.run(-->)THREAD2【55sxf】 时间: 19:39:06 130 57 MyThread.run(-->)THREAD0【56sxf】 时间: 19:39:06 130 58 MyThread.run(-->)THREAD3【57sxf】 时间: 19:39:06 130 59 MyThread.run(-->)THREAD1【58sxf】 时间: 19:39:06 130 60 MyThread.run(-->)THREAD3【61sxf】 时间: 19:39:06 131 61 MyThread.run(-->)THREAD2【59sxf】 时间: 19:39:06 131 62 MyThread.run(-->)THREAD0【60sxf】 时间: 19:39:06 131 63 MyThread.run(-->)THREAD1【62sxf】 时间: 19:39:06 131 64 MyThread.run(-->)THREAD3【63sxf】 时间: 19:39:06 131 65 MyThread.run(-->)THREAD0【65sxf】 时间: 19:39:06 131 66 MyThread.run(-->)THREAD1【66sxf】 时间: 19:39:06 131 67 MyThread.run(-->)THREAD3【67sxf】 时间: 19:39:06 131 68 MyThread.run(-->)THREAD0【68sxf】 时间: 19:39:06 131 69 MyThread.run(-->)THREAD1【69sxf】 时间: 19:39:06 131 70 MyThread.run(-->)THREAD3【70sxf】 时间: 19:39:06 131 71 MyThread.run(-->)THREAD2【64sxf】 时间: 19:39:06 131 72 MyThread.run(-->)THREAD0【71sxf】 时间: 19:39:06 131 73 MyThread.run(-->)THREAD2【74sxf】 时间: 19:39:06 132 74 MyThread.run(-->)THREAD3【73sxf】 时间: 19:39:06 131 75 MyThread.run(-->)THREAD0【75sxf】 时间: 19:39:06 132 76 MyThread.run(-->)THREAD2【76sxf】 时间: 19:39:06 132 77 MyThread.run(-->)THREAD0【78sxf】 时间: 19:39:06 132 78 MyThread.run(-->)THREAD2【79sxf】 时间: 19:39:06 132 79 MyThread.run(-->)THREAD0【80sxf】 时间: 19:39:06 132 80 MyThread.run(-->)THREAD2【81sxf】 时间: 19:39:06 132 81 MyThread.run(-->)THREAD0【82sxf】 时间: 19:39:06 132 82 MyThread.run(-->)THREAD2【83sxf】 时间: 19:39:06 132 83 MyThread.run(-->)THREAD0【84sxf】 时间: 19:39:06 132 84 MyThread.run(-->)THREAD2【85sxf】 时间: 19:39:06 132 85 MyThread.run(-->)THREAD0【86sxf】 时间: 19:39:06 132 86 MyThread.run(-->)THREAD2【87sxf】 时间: 19:39:06 132 87 MyThread.run(-->)THREAD0【88sxf】 时间: 19:39:06 132 88 MyThread.run(-->)THREAD2【89sxf】 时间: 19:39:06 132 89 MyThread.run(-->)THREAD0【90sxf】 时间: 19:39:06 132 90 MyThread.run(-->)THREAD2【91sxf】 时间: 19:39:06 132 91 MyThread.run(-->)THREAD1【72sxf】 时间: 19:39:06 131 92 MyThread.run(-->)THREAD0【92sxf】 时间: 19:39:06 133 93 MyThread.run(-->)THREAD3【77sxf】 时间: 19:39:06 132 94 MyThread.run(-->)THREAD2【93sxf】 时间: 19:39:06 133 95 MyThread.run(-->)THREAD0【95sxf】 时间: 19:39:06 133 96 MyThread.run(-->)THREAD1【94sxf】 时间: 19:39:06 133 97 MyThread.run(-->)THREAD3【96sxf】 时间: 19:39:06 133 98 MyThread.run(-->)THREAD0【98sxf】 时间: 19:39:06 133 99 MyThread.run(-->)THREAD2【97sxf】 时间: 19:39:06 133 100 MyThread.run(-->)THREAD3notfyAll() 101 MyThread.run(-->)THREAD2notfyAll() 102 MyThread.run(-->)THREAD0notfyAll() 103 MyThread.run(-->)THREAD1【99sxf】 时间: 19:39:06 133 104 MyThread.run(-->)THREAD1notfyAll() 105 Test.main(完成时间:)19:39:06 133