今日内容
一、多线程之间通信
1.生产者与消费者
package com.itmayiedu;
// 共享对象
class Res {
// 姓名
public String name;
// 性别
public String sex;
}
// 生产这线程
class IntThread extends Thread {
public Res res;
public IntThread(Res res) {
this.res = res;
}
@Override
public void run() {
int count = 0; // 1
while (true) {
synchronized (res) {
if (count == 0) {
res.name = "小红";
res.sex = "女";
} else {
res.name = "小军";
res.sex = "男";
}
count = (count + 1) % 2;// 0 1 0 1 0 1
}
}
}
}
// 读取线程
class OutThread extends Thread {
public Res res;
public OutThread(Res res) {
this.res = res;
}
@Override
public void run() {
while (true) {
synchronized (res) {
System.out.println(res.name + "," + res.sex);
}
}
}
}
public class Test0001 {
public synchronized static void main(String[] args) throws InterruptedException {
Res res = new Res();
IntThread intThread = new IntThread(res);
OutThread outThread = new OutThread(res);
intThread.start();
outThread.start();
}
}
2.wait与notify区别
package com.itmayiedu;
// 共享对象
class Res {
// 姓名
public String name;
// 性别
public String sex;
// 为true情况下 允许读,不能写
// 为false情况下 允许写,不能读。
public boolean flag = false;
}
// 生产这线程
class IntThread extends Thread {
public Res res;
public IntThread(Res res) {
this.res = res;
}
@Override
public void run() {
int count = 0; // 1
while (true) {
synchronized (res) {
if (res.flag) {
try {
res.wait();// 釋放当前锁对象
} catch (Exception e) {
// TODO: handle exception
}
}
if (count == 0) {
res.name = "小红";
res.sex = "女";
} else {
res.name = "小军";
res.sex = "男";
}
count = (count + 1) % 2;// 0 1 0 1 0 1
res.flag = true;// 标记当前线程为等待
res.notify();// 唤醒被等待的线程
}
}
}
}
// 读取线程
class OutThread extends Thread {
public Res res;
public OutThread(Res res) {
this.res = res;
}
@Override
public void run() {
while (true) {
synchronized (res) {
try {
if (!res.flag) {
res.wait();
}
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
System.out.println(res.name + "," + res.sex);
res.flag = false;
res.notify();
}
}
}
}
public class Test0001 {
public synchronized static void main(String[] args) throws InterruptedException {
Res res = new Res();
IntThread intThread = new IntThread(res);
OutThread outThread = new OutThread(res);
intThread.start();
outThread.start();
}
}
wait、notify方法总结:
1.因为涉及到对象锁,他们必须都放在synchronized中来使用. Wait、Notify一定要在synchronized里面进行使用。
2.Wait必须暂定当前正在执行的线程,并释放资源锁,让其他线程可以有机会运行
3. notify/notifyall: 唤醒因锁池中的线程,使之运行注意:一定要在线程同步中使用,并且是同一个锁的资源
3.阻塞队列与非阻塞队列
阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列。
1.ArrayDeque, (数组双端队列)
2.PriorityQueue, (优先级队列)
3.ConcurrentLinkedQueue, (基于链表的并发队列)
4.DelayQueue, (延期阻塞队列)(阻塞队列实现了BlockingQueue接口)
5.ArrayBlockingQueue, (基于数组的并发阻塞队列)
6.LinkedBlockingQueue, (基于链表的FIFO阻塞队列)
7.LinkedBlockingDeque, (基于链表的FIFO双端阻塞队列)
8.PriorityBlockingQueue, (带优先级的无界阻塞队列)
9.SynchronousQueue (并发同步阻塞队列)
4.使用并发队列实现生产者与消费者
class ProducerThread implements Runnable {
private BlockingQueue<String> blockingQueue;
private AtomicInteger count = new AtomicInteger();
private volatile boolean FLAG = true;
public ProducerThread(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "生产者开始启动....");
while (FLAG) {
String data = count.incrementAndGet() + "";
try {
boolean offer = blockingQueue.offer(data, 2, TimeUnit.SECONDS);
if (offer) {
System.out.println(Thread.currentThread().getName() + ",生产队列" + data + "成功..");
} else {
System.out.println(Thread.currentThread().getName() + ",生产队列" + data + "失败..");
}
Thread.sleep(1000);
} catch (Exception e) {
}
}
System.out.println(Thread.currentThread().getName() + ",生产者线程停止...");
}
public void stop() {
this.FLAG = false;
}
}
class ConsumerThread implements Runnable {
private volatile boolean FLAG = true;
private BlockingQueue<String> blockingQueue;
public ConsumerThread(BlockingQueue<String> blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "消费者开始启动....");
while (FLAG) {
try {
String data = blockingQueue.poll(2, TimeUnit.SECONDS);
if (data == null || data == "") {
FLAG = false;
System.out.println("消费者超过2秒时间未获取到消息.");
return;
}
System.out.println("消费者获取到队列信息成功,data:" + data);
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
public class Test0008 {
public static void main(String[] args) {
BlockingQueue<String> blockingQueue = new LinkedBlockingQueue<>(3);
ProducerThread producerThread = new ProducerThread(blockingQueue);
ConsumerThread consumerThread = new ConsumerThread(blockingQueue);
Thread t1 = new Thread(producerThread);
Thread t2 = new Thread(consumerThread);
t1.start();
t2.start();
//10秒后 停止线程..
try {
Thread.sleep(10*1000);
producerThread.stop();
} catch (Exception e) {
// TODO: handle exception
}
}
}
5.线程池的作用
6.executors四种线程池用法
package com.itmayiedu;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test0001 {
public static void main(String[] args) {
//可以缓存的线程池
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int temp=i;
// 可执行线程 execute 方法表示启动线程
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId()+",i"+temp);
}
});
}
}
}
package com.itmayiedu;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test0002 {
public static void main(String[] args) {
// 控制并发数的线程池
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int temp = i;
newFixedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "," + temp);
}
});
}
}
}
package com.itmayiedu;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test0003 {
public static void main(String[] args) {
// 可以定时线程池
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(3);
for (int i = 0; i < 10; i++) {
final int temp = i;
newScheduledThreadPool.schedule(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()+",i:" + temp);
}
}, 3, TimeUnit.SECONDS);
}
}
}
package com.itmayiedu;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test0004 {
public static void main(String[] args) {
ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int temp = i;
newSingleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ",i:" + temp);
}
});
}
}
}
7.线程池实现原理