有关Java多线程,前面我记录自己对于线程池创建的两种方式,以及线程池如何创建线程(这里自己在加深一下印象:当执行execute方法时候,会将任务放入addWorker方法中,addWorker将任务放入到Worker构造器中,该类中runWorker方法有一个getTask方法,这个方法中有一段代码:boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();会从队列中取出任务执行,否则take()核心线程进行阻塞,保证核心线程不被销毁)
在多线程并发任务中,很多并发问题是由于对于JVM中主内存(主要包括方法区和堆,有关JVM知识可以自行查阅)中共享变量的不安全操作。所以我觉得就扯出来锁,目前我所知道的就是乐观锁/悲观锁,公平锁/非公平锁,互斥锁/读写锁(ReentrantLock/ReadWriteLock)以及自旋锁,分段锁(concurrentHashMap)。这些锁在不同场景的应用能够解决不同的并发问题。我又想扯到AQS中,但是我理解还很肤浅,不在叙述,开始实现生产者消费者模式:
我这里用两种方法去实现:
一种是利用BlockingQueue,一种是利用Condition(多线程间协调通信工具类)的await、signalAll
package com.elastic.search.ProCus;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ProCus {
public static void main(String[] args) {
//new ProCus().BloQueueTest(); // BlockingQueue
new ProCus().ConditionTest(); // await signalAll
}
public void BloQueueTest() {
Queue queue = new Queue();
new Thread(new Producer(queue), "pro1").start();
new Thread(new Customer(queue), "c1").start();
new Thread(new Customer(queue), "c2").start();
new Thread(new Customer(queue), "c3").start();
}
public void ConditionTest() {
Lock lock = new ReentrantLock();
Condition producer = lock.newCondition();
Condition customer = lock.newCondition();
Cache cache = new Cache(lock, producer, customer);
new Thread(new Produce2(cache), "p1").start();
new Thread(new Customer2(cache), "c1").start();
new Thread(new Customer2(cache), "c2").start();
}
}
class Queue {
private BlockingQueue blockingQueue = new LinkedBlockingQueue(10);
public void Producer() {
try {
blockingQueue.put(1);
System.out.println(Thread.currentThread().getName() + "生产,当前资源数:" + blockingQueue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void customer() {
try {
System.out.println(Thread.currentThread().getName() + "进入到队列中准备消耗资源,此时资源池数量:" + blockingQueue.size());
blockingQueue.take();
System.out.println(Thread.currentThread().getName() + "消耗,当前资源数:" + blockingQueue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Producer implements Runnable {
private Queue queue;
public Producer(Queue queue) {
this.queue = queue;
}
@Override
public void run() {
for (; ; ) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
queue.Producer();
}
}
}
class Customer implements Runnable {
private Queue queue;
public Customer(Queue queue) {
this.queue = queue;
}
@Override
public void run() {
for (; ; ) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
queue.customer();
}
}
}
class Cache {
int size = 10;
int num = 0;
private Lock lock;
private Condition proCondition;
private Condition cusCondition;
Cache(Lock lock, Condition proCondition, Condition cusCondition) {
this.lock = lock;
this.cusCondition = cusCondition;
this.proCondition = proCondition;
}
public void producer() {
lock.lock();
try {
if (size > num) {
num++;
System.out.println(Thread.currentThread().getName() + "product,num:" + num);
cusCondition.signalAll();
} else {
try {
System.out.println("size > num pro await");
proCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
}
}
public void customer() {
lock.lock();
try {
if (num > 0) {
num--;
System.out.println(Thread.currentThread().getName() + "customer,num:" + num);
proCondition.signalAll();
} else {
try {
System.out.println(" num < 0 cus await");
cusCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} finally {
lock.unlock();
}
}
}
class Produce2 implements Runnable {
private Cache cache;
Produce2(Cache cache) {
this.cache = cache;
}
@Override
public void run() {
for (; ; ) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cache.producer();
}
}
}
class Customer2 implements Runnable {
private Cache cache;
Customer2(Cache cache) {
this.cache = cache;
}
@Override
public void run() {
for (; ; ) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cache.customer();
}
}
}