4月11日java多线程4

继昨天学习了线程池之后,今天学习了多线程内的锁Lock。

定义方法:

ReentrantLock queueLock = new ReentrantLock(); //可重入锁

ReentrantReadWriteLock orderLock = new ReentrantReadWriteLock(); //可重入读写锁

每个锁都有个lock方法(上锁)和unlock方法(释放锁)

在写入锁的时候只能有一个线程,但是读取锁的时候可以线程一起共享锁里面的代码

今天还学习了信号量Semphore 自己定义最大可以同时运行多少线程

定义方法:

Semaphore placeSemaphore = new Semaphore(5);

使用acquire方法获得信号量 总信号量-1

使用release方法释放信号量 总信号量+1

附今日的代码:

  1 import java.util.concurrent.locks.ReentrantLock;
  2 import java.util.concurrent.locks.ReentrantReadWriteLock;
  3 
  4 public class LockExample {
  5 
  6     private static final ReentrantLock queueLock = new ReentrantLock(); //可重入锁
  7     private static final ReentrantReadWriteLock orderLock = new ReentrantReadWriteLock(); //可重入读写锁
  8     
  9     /**
 10      * 有家奶茶店,点单有时需要排队 
 11      * 假设想买奶茶的人如果看到需要排队,就决定不买
 12      * 又假设奶茶店有老板和多名员工,记单方式比较原始,只有一个订单本
 13      * 老板负责写新订单,员工不断地查看订单本得到信息来制作奶茶,在老板写新订单时员工不能看订单本
 14      * 多个员工可同时看订单本,在员工看时老板不能写新订单
 15      * @param args
 16      * @throws InterruptedException 
 17      */
 18     public static void main(String[] args) throws InterruptedException {
 19         //buyMilkTea();
 20         handleOrder(); //需手动关闭
 21     }
 22     
 23     public void tryToBuyMilkTea() throws InterruptedException {
 24         boolean flag = true;
 25         while(flag)
 26         {
 27             //判断queneLock现在是什么状态,如果是锁住的状态就返回false,如果是空闲状态则将它锁住返回true。
 28             if (queueLock.tryLock()) {
 29                 //queueLock.lock();
 30                 //随机睡眠一段时间
 31                 long thinkingTime = (long) (Math.random() * 500);
 32                 Thread.sleep(thinkingTime);
 33                 System.out.println(Thread.currentThread().getName() + ": 来一杯珍珠奶茶,不要珍珠");
 34                 flag = false;
 35                 //将锁释放
 36                 queueLock.unlock();
 37             } else {
 38                 //System.out.println(Thread.currentThread().getName() + ":" + queueLock.getQueueLength() + "人在排队");
 39                 System.out.println(Thread.currentThread().getName() + ": 再等等");
 40             }
 41             if(flag)
 42             {
 43                 Thread.sleep(1000);
 44             }
 45         }
 46         
 47     }
 48     
 49     public void addOrder() throws InterruptedException {
 50         //写入锁 锁住的情况下只能一个线程写
 51         orderLock.writeLock().lock();
 52         //睡眠一段时间
 53         long writingTime = (long) (Math.random() * 1000);
 54         Thread.sleep(writingTime);
 55         System.out.println("老板新加一笔订单");
 56         //释放锁
 57         orderLock.writeLock().unlock();
 58     }
 59     
 60     public void viewOrder() throws InterruptedException {
 61         //读取锁 锁住的情况下可以多个线程一起共享
 62         orderLock.readLock().lock();
 63         //睡眠一段时间
 64         long readingTime = (long) (Math.random() * 500);
 65         Thread.sleep(readingTime);
 66         System.out.println(Thread.currentThread().getName() + ": 查看订单本");
 67         //释放锁
 68         orderLock.readLock().unlock();            
 69 
 70     }
 71     
 72     //买奶茶方法
 73     public static void buyMilkTea() throws InterruptedException {
 74         LockExample lockExample = new LockExample();
 75         //定义线程数
 76         int STUDENTS_CNT = 10;
 77         //建立线程
 78         Thread[] students = new Thread[STUDENTS_CNT];
 79         for (int i = 0; i < STUDENTS_CNT; i++) {
 80             //给每个线程完成初始化
 81             students[i] = new Thread(new Runnable() {
 82 
 83                 @Override
 84                 public void run() {
 85                     try {
 86                         //随机睡眠一段时间
 87                         long walkingTime = (long) (Math.random() * 1000);
 88                         Thread.sleep(walkingTime);
 89                         //尝试现在是否能够买奶茶
 90                         lockExample.tryToBuyMilkTea();
 91                     } catch(InterruptedException e) {
 92                         System.out.println(e.getMessage());
 93                     }
 94                 }
 95                 
 96             }
 97             );
 98             //让所有线程开始工作
 99             students[i].start();
100         }
101         
102         for (int i = 0; i < STUDENTS_CNT; i++)
103             //等待所有线程结束
104             students[i].join();
105 
106     }
107     
108     
109     public static void handleOrder() throws InterruptedException {
110         LockExample lockExample = new LockExample();
111         
112         //创建了一个老板写的线程类并且完成了初始化。
113         Thread boss = new Thread(new Runnable() {
114 
115             @Override
116             public void run() {
117                 while (true) {
118                     try {
119                         //添加订单
120                         lockExample.addOrder();
121                         //随机睡眠一段时间
122                         long waitingTime = (long) (Math.random() * 1000);
123                         Thread.sleep(waitingTime);
124                     } catch (InterruptedException e) {
125                         System.out.println(e.getMessage());
126                     }
127                 }
128             }
129         });
130         //老板线程开始
131         boss.start();
132         //定义员工线程数
133         int workerCnt = 3;
134         //创建员工线程
135         Thread[] workers = new Thread[workerCnt];
136         for (int i = 0; i < workerCnt; i++)
137         {
138             //给每个员工线程初始化
139             workers[i] = new Thread(new Runnable() {
140 
141                 @Override
142                 public void run() {
143                     while (true) {
144                         try {
145                                 //查看订单
146                                 lockExample.viewOrder();
147                                 //睡眠一段时间
148                                 long workingTime = (long) (Math.random() * 5000);
149                                 Thread.sleep(workingTime);
150                             } catch (InterruptedException e) {
151                                 System.out.println(e.getMessage());
152                             }
153                         }
154                 }
155                 
156             });
157             //员工线程开始工作
158             workers[i].start();
159         }
160         
161     }
162 }
 1 import java.util.concurrent.Semaphore;
 2 
 3 public class SemaphoreExample {
 4     //定义了5个车位
 5     private final Semaphore placeSemaphore = new Semaphore(5);
 6     
 7     public boolean parking() throws InterruptedException {
 8         //如果此时Semaphore信号量不为0就会获取一个信号量返回true并且信号量-1,如果信号量为0的话则返回false
 9         if (placeSemaphore.tryAcquire()) {
10             System.out.println(Thread.currentThread().getName() + ": 停车成功");
11             return true;
12         } else {
13             System.out.println(Thread.currentThread().getName() + ": 没有空位");
14             return false;
15         }
16 
17     }
18     
19     public void leaving() throws InterruptedException {
20         //释放掉一个信号量,信号量+1
21         placeSemaphore.release();
22         System.out.println(Thread.currentThread().getName() + ": 开走");
23     }
24     
25     /**
26      * 现有一地下车库,共有车位5个,由10辆车需要停放,每次停放时,去申请信号量
27      * @param args
28      * @throws InterruptedException 
29      */
30     public static void main(String[] args) throws InterruptedException {
31         //定义总共要停车的数量
32         int tryToParkCnt = 10;
33         
34         SemaphoreExample semaphoreExample = new SemaphoreExample();
35         //创建要停车的数量的线程
36         Thread[] parkers = new Thread[tryToParkCnt];
37         
38         for (int i = 0; i < tryToParkCnt; i++) {
39             //将每个线程进行初始化
40             parkers[i] = new Thread(new Runnable() {
41 //这是视频里面的源代码,我在运行之后发现结果和我想象中的有点不同,因为有的车没有停到车位,不是等待之后再停车,而是直接没有停车了。
42 //原因是不管if里面返回true或是false都只会执行一次,如果是false的话就只输出了一个没有空位,然后线程就结束了。
43 //所以我在if判断的外面加了一个while死循环,当if为true,车成功的停车然后离开车位之后break退出循环。
44 //                @Override
45 //                public void run() {
46 //                    try {
47 //                        long randomTime = (long) (Math.random() * 1000);
48 //                        Thread.sleep(randomTime);
49 //                        if (semaphoreExample.parking()) {
50 //                            long parkingTime = (long) (Math.random() * 1200);
51 //                            Thread.sleep(parkingTime);
52 //                            semaphoreExample.leaving();
53 //                        }
54 //                    } catch (InterruptedException e) {
55 //                        e.printStackTrace();
56 //                    }
57 //                }
58                 @Override
59                 public void run() {
60                     try {
61                         exit:
62                         while(true)
63                         {    
64                             //睡眠一段时间
65                             long randomTime = (long) (Math.random() * 1000);
66                             Thread.sleep(randomTime);
67                             //尝试进行停车,如果停车成功会返回true
68                             if (semaphoreExample.parking()) {
69                                 //睡眠一段时间,然后调用离开方法
70                                 long parkingTime = (long) (Math.random() * 1200);
71                                 Thread.sleep(parkingTime);
72                                 semaphoreExample.leaving();
73                                 break exit;
74                             }
75                         }
76                     } catch (InterruptedException e) {
77                         e.printStackTrace();
78                     }
79                 }
80             });
81             //让每个线程开始工作
82             parkers[i].start();
83         }
84 
85         for (int i = 0; i < tryToParkCnt; i++) {
86             //等待每个线程结束
87             parkers[i].join();
88         }    
89     }
90 }

 

上一篇:面试又双叒叕被问到数据库三大范式,该怎么答才能让面试官认可呢


下一篇:Django原生SQL语句查询返回字典