多线程&JUC-CSDN博客
生产者消费者问题
用wait和notify方法实现容量为1的桌子的情况
public class Eater extends Thread {
public Eater() {
}
public Eater(String name) {
super(name);
}
@Override
public void run() {
while (true){
synchronized (Desk.lock){
if(Desk.foodNum>0){
System.out.println("消费者吃");
Desk.foodNum--;
}
else {
try {
Desk.lock.wait();//当前线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public class Cook extends Thread{
public Cook() {
}
public Cook(String name) {
super(name);
}
@Override
public void run() {
while (true){
synchronized (Desk.lock){
if(Desk.foodNum==0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产者做");
Desk.foodNum++;
Desk.lock.notifyAll();
}
else {
}
}
}
}
}
public class Desk {
static Lock lock=new ReentrantLock();
static int foodNum=0;//桌上没有食物,桌子的容量为1
public static void main(String[] args) {
Eater eater = new Eater();
Cook cook = new Cook();
eater.start();
cook.start();
}
}
用阻塞队列实现容量为10的桌子的情况
package com.example.testThread2;
import com.example.testThread2.Cook;
import com.example.testThread2.Eater;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Desk {
//用阻塞队列实现容量为10的桌子
static ArrayBlockingQueue<String> queue=new ArrayBlockingQueue<String>(10);
public static void main(String[] args) {
Eater eater = new Eater();
Cook cook = new Cook();
eater.start();
cook.start();
}
}
package com.example.testThread2;
public class Eater extends Thread {
public Eater() {
}
public Eater(String name) {
super(name);
}
@Override
public void run() {
while (true){
try {
Thread.sleep(600);
Desk.queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("消费者吃了一碗面条,现在桌上还有"+Desk.queue.size()+"碗");
}
}
}
package com.example.testThread2;
public class Cook extends Thread{
public Cook() {
}
public Cook(String name) {
super(name);
}
@Override
public void run() {
while (true){
try {
if(Desk.queue.size()>5)
{
Thread.sleep(1000);
Desk.queue.put("面条");
}
else {
Thread.sleep(300);
Desk.queue.put("面条");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("生产者做了一碗面条,现在桌上还有"+Desk.queue.size()+"碗");
}
}
}
线程的状态
实际上java中定义的线程状态只有其中的6种,不包括上图的运行状态,因为运行时JVM把线程交给操作系统处理了。
线程池
线程池核心原理
线程池代码实现
public class PoolTask implements Runnable{
@Override
public void run() {
// for (int i = 0; i < 100; i++) {
// System.out.println(Thread.currentThread().getName()+":"+i);
// }
System.out.println(Thread.currentThread().getName());
}
}
@Test
public void test05() throws InterruptedException {
/*
线程池
*/
//1.创建线程池对象
// ExecutorService threadPool = Executors.newCachedThreadPool();
ExecutorService threadPool = Executors.newFixedThreadPool(3);//创建一个上限为3的线程池
//2.提交任务
threadPool.submit(new PoolTask());
threadPool.submit(new PoolTask());
// Thread.sleep(1000);
threadPool.submit(new PoolTask());
// Thread.sleep(1000);
threadPool.submit(new PoolTask());
// Thread.sleep(1000);
threadPool.submit(new PoolTask());
//销毁线程池
threadPool.shutdown();
}
上限为3的线程池
无上限的线程池
自定义线程池
相关参数
情况1 :何时创建临时进程
核心线程----->等待队列----->临时线程
情况2:什么情况下触发拒绝策略
答:核心线程、等待队列、临时线程都被占用了。
4种任务拒绝策略
采用第三种策略,将抛弃任务4
自定义线程池初体验
@Test
public void test07(){
//两个核心线程+两个临时线程+长度为2的等待队列
ThreadPoolExecutor myThreadPool = new ThreadPoolExecutor(
2,//核心线程数
4,//最大线程数
1,//空闲线程最大存活时间
TimeUnit.MINUTES,//时间单位
new ArrayBlockingQueue<>(2),//长度为3的等待队列
Executors.defaultThreadFactory(),//创建线程工厂
new ThreadPoolExecutor.AbortPolicy()//设置拒绝策略:丢弃任务并抛出异常
);
myThreadPool.submit(new PoolTask());
myThreadPool.submit(new PoolTask());
myThreadPool.submit(new PoolTask());
myThreadPool.submit(new PoolTask());
myThreadPool.submit(new PoolTask());
myThreadPool.submit(new PoolTask());
myThreadPool.submit(new PoolTask());//到这里就执行拒绝策略了
myThreadPool.submit(new PoolTask());
myThreadPool.submit(new PoolTask());
myThreadPool.submit(new PoolTask());
myThreadPool.shutdown();
}
怎样设计线程池?
最大并行数=8*2=16
对于CPU密集型计算,以我电脑的配置,线程池的最大线程数可设为:16+1=17