线程同步(synchronized)(重点)
-
同步方法(同步方法,锁的是this类本身)
-
同步块(synchronized(Obj){})
- Obj称为同步监视器
死锁
lock(锁)ReentrantLock类(可重入锁)实现Lock,可以显示加锁、释放锁。
package com.fjbc.多线程;
import java.util.concurrent.locks.ReentrantLock;
//测试Lock锁
public class Demo32_ThreadLock {
public static void main(String[] args) {
TestLock testLock = new TestLock();
new Thread(testLock).start();
new Thread(testLock).start();
new Thread(testLock).start();
}
}
class TestLock implements Runnable {
int tickerNums = 10;
//定义Lock锁
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
//加锁
try {
lock.lock();
if (tickerNums <= 0) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(tickerNums--);
} catch (Exception e) {
e.printStackTrace();
} finally {
//解锁
lock.unlock();
}
}
}
}
(难)线程协作通信(生产者消费者模式)
-
管程法
-
package com.fjbc.多线程; /** * 测试:生产者消费者模型-->利用缓冲区解决:管程法 */ public class Demo33_ThreadPC { public static void main(String[] args) { SynContainer synContainer = new SynContainer(); new Producer(synContainer).start(); new Consumer(synContainer).start(); } } //生产者 class Producer extends Thread { //容缓冲区 SynContainer container; public Producer(SynContainer container) { this.container = container; } //生产 @Override public void run() { for (int i = 0; i < 100; i++) { container.push(new Product(i)); System.out.println("生产了" + i + "件产品"); } } } //消费者 class Consumer extends Thread { //容缓冲区 SynContainer container; public Consumer(SynContainer container) { this.container = container; } //消费 @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("消费了-->" + container.pop().id + "件产品"); } } } //产品 class Product { int id;//产品编号 public Product(int id) { this.id = id; } } //缓冲区 class SynContainer { //需要一个容器大小 Product[] products = new Product[10]; //容器计数器 int count = 0; //生产者放入产品 public synchronized void push(Product product) { //如果容器满了,需要等待消费者消费 /*如果是if的话,假如消费者1消费了最后一个,这是index变成0此时释放锁被消费者2拿到而不是生产者拿到,这时消费者的wait是在if里所以它就直接去消费index-1下标越界,如果是while就会再去判断一下index得值是不是变成0了*/ while (count == products.length) { //通知消费者消费,等待生产 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果没有满,需要丢入产品 products[count] = product; count++; //通知消费者消费 this.notifyAll(); } //消费者消费产品 public synchronized Product pop() { //判断是否能消费 while (count <= 0) { //等待生产者生产 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果可以消费 count--; Product product = products[count]; //吃完了 通知生产者生产 this.notifyAll(); return product; } }
-
-
信号灯法
-
package com.fjbc.多线程; public class Demo34_ThreadPool { /** * 测试:生产者消费者模型-->利用缓冲区解决:管程法 */ public static void main(String[] args) { SynContainer synContainer = new SynContainer(); new Producer(synContainer).start(); new Consumer(synContainer).start(); } } //生产者 class Producer1 extends Thread { //容缓冲区 SynContainer container; public Producer1(SynContainer container) { this.container = container; } //生产 @Override public void run() { for (int i = 0; i < 100; i++) { container.push(new Product(i)); System.out.println("生产了" + i + "件产品"); } } } //消费者 class Consumer1 extends Thread { //容缓冲区 SynContainer container; public Consumer1(SynContainer container) { this.container = container; } //消费 @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("消费了-->" + container.pop().id + "件产品"); } } } //产品 class Product1 { int id;//产品编号 public Product1(int id) { this.id = id; } } //缓冲区 class SynContainer1 { //需要一个容器大小 Product[] products = new Product[10]; //容器计数器 int count = 0; //生产者放入产品 public synchronized void push(Product product) { //如果容器满了,需要等待消费者消费 /*如果是if的话,假如消费者1消费了最后一个,这是index变成0此时释放锁被消费者2拿到而不是生产者拿到,这时消费者的wait是在if里所以它就直接去消费index-1下标越界,如果是while就会再去判断一下index得值是不是变成0了*/ while (count == products.length) { //通知消费者消费,等待生产 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果没有满,需要丢入产品 products[count] = product; count++; //通知消费者消费 this.notifyAll(); } //消费者消费产品 public synchronized Product pop() { //判断是否能消费 while (count <= 0) { //等待生产者生产 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果可以消费 count--; Product product = products[count]; //吃完了 通知生产者生产 this.notifyAll(); return product; } }
-
使用线程池
-
- 创建服务,创建线程池(newFixedThreadPool(线程池大小)):ExecutorService service = Executors.newFixedThreadPool(10);
- 执行(service.execute(new MyThread());)
- 关闭连接(service.shutdown();)