- Executor
package concurrent.executor;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
* public static ExecutorService newFixedThreadPool(int nThreads)
* 创建固定数目线程的线程池。
* public static ExecutorService newCachedThreadPool()
* 创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
* public static ExecutorService newSingleThreadExecutor()
* 创建一个单线程化的Executor。
* public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
* @author xiaoyang
*
*/
public class TaskExecutorWebServer {
private static final Executor exec=Executors.newFixedThreadPool(100);
public static void main(String[] args) throws Exception {
ServerSocket ss=new ServerSocket(8888);
while(true){
final Socket connection= ss.accept();
Runnable task=new Runnable() {
@Override
public void run() {
//handleRequest(connection);
}
};
exec.execute(task);
}
}
}
<span style="font-size: 24px; font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">Executorservice</span>
package concurrent.executorservice;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* ExecutorService扩展了Executor并添加了一些生命周期管理的方法。一个Executor的生命周期有三种状态,运行 ,关闭 ,终止 。Executor创建时处于运行状态。当调用ExecutorService.shutdown()后,处于关闭状态,isShutdown()方法返回true。这时,不应该再想Executor中添加任务,所有已添加的任务执行完毕后,Executor处于终止状态,isTerminated()返回true。
*如果Executor处于关闭状态,往Executor提交任务会抛出unchecked exception RejectedExecutionException。
* @author xiaoyang
*
*/
public class LifecycleWebServer {
private final ExecutorService exec=Executors.newFixedThreadPool(100);
public void start() throws Exception {
ServerSocket ss=new ServerSocket(8888);
while(!exec.isShutdown()){
final Socket connection= ss.accept();
Runnable task=new Runnable() {
@Override
public void run() {
//handleRequest(connection);
}
};
exec.execute(task);
}
}
public void stop(){
exec.shutdown();
}
}
package concurrent.executorservice;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Future<V>代表一个异步执行的操作,通过get()方法可以获得操作的结果,如果异步操作还没有完成,则,get()会使当前线程阻塞。FutureTask<V>实现了Future<V>和Runable<V>。Callable代表一个有返回值得操作。
* @author xiaoyang
*/
public class CallableLifecycleWebServer {
private final ExecutorService exec=Executors.newFixedThreadPool(100);
public void start() throws Exception {
ServerSocket ss=new ServerSocket(8888);
while(!exec.isShutdown()){
final Socket connection= ss.accept();
Callable<Object> task=new Callable<Object>() {
@Override
public Object call() {
//return handleRequest(connection);
return null;
}
};
Future<Object> f= exec.submit(task);
Object result= f.get();
}
}
public void stop(){
exec.shutdown();
}
}
ExecutorThreadPool
package concurrent.ExecutorThreadPool;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)
*corePoolSize:池中所保存的线程数,包括空闲线程(非最大同时干活的线程数)。如果池中线程数多于 corePoolSize,则这些多出的线程在空闲时间超过 keepAliveTime 时将会终止。
*maximumPoolSize:线程池中最大线程数
*keepAliveTime:线程空闲回收的时间
*unit:keepAliveTime的单位
*workQueue:保存任务的队列,可以如下选择:
* • 无界队列: new LinkedBlockingQueue<Runnable>();
* • 有界队列: new ArrayBlockingQueue<Runnable>(8);你不想让客户端无限的请求吃光你的CPU和内存吧,那就用有界队列
*handler:当提交任务数大于队列size会抛出RejectedExecutionException,可选的值为:
* •ThreadPoolExecutor.CallerRunsPolicy 等待队列空闲
*•ThreadPoolExecutor.DiscardPolicy:丢弃要插入队列的任务
*•ThreadPoolExecutor.DiscardOldestPolicy:删除队头的任务
*
* @author xiaoyang
*
*/
public class ExecutorThreadPoolDemo_ {
public static void main(String[] args) {
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 1, TimeUnit.DAYS, queue);
for (int i = 0; i < 20; i++) {
final int index = i;
executor.submit(new Runnable() {
public void run() {
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(String.format("thread %d finished", index));
}
});
}
executor.shutdown();
}
}
SchedualExecutorService
package concurrent.schedual_executor_service;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* ScheduledExecutorService接口
*在ExecutorService的基础上,ScheduledExecutorService提供了按时间安排执行任务的功能,它提供的方法主要有:
*•schedule(task,initDelay):安排所提交的Callable或Runnable任务在initDelay指定的时间后执行。
*•scheduleAtFixedRate():安排所提交的Runnable任务按指定的间隔重复执行
*•scheduleWithFixedDelay():安排所提交的Runnable任务在每次执行完后,等待delay所指定的时间后重复执行。
*@author xiaoyang
*/
public class ScheduledExecutorServiceTest {
private static final ScheduledExecutorService service=Executors.newScheduledThreadPool(2);
public static void main(String[] args) throws Exception {
Runnable task1=new Runnable() {
@Override
public void run() {
System.out.println("task1 running ");
}
};
@SuppressWarnings("rawtypes")
final ScheduledFuture future1=service.scheduleAtFixedRate(task1, 1, 10, TimeUnit.SECONDS);
final ScheduledFuture<String> future2=service.schedule(new Callable<String>() {
@Override
public String call() throws Exception {
future1.cancel(true);
return "task1 cancelled!";
}
}, 20, TimeUnit.SECONDS);
System.out.println(future2.get());
service.shutdown();
}
}
CompletionService
package concurrent.CompletionService;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @author xiaoyang
*
*/
public class CompletionServiceTest {
public static void main(String[] args) throws Exception {
CompletionServiceTest t = new CompletionServiceTest();
t.count1();
t.count2();
}
//使用阻塞容器保存每次Executor处理的结果,在后面进行统一处理
public void count1() throws Exception{
long time1=System.currentTimeMillis();
ExecutorService exec = Executors.newCachedThreadPool();
BlockingQueue<Future<Integer>> queue = new LinkedBlockingQueue<Future<Integer>>();
for(int i=0; i<100; i++){
Future<Integer> future =exec.submit(getTask());
queue.add(future);
}
int sum = 0;
int queueSize = queue.size();
for(int i=0; i<queueSize; i++){
sum += queue.take().get();
}
long time2=System.currentTimeMillis();
System.out.println("总数为:"+sum);
System.out.println("共耗时:"+(time2-time1));
exec.shutdown();
}
//使用CompletionService(完成服务)保持Executor处理的结果
public void count2() throws InterruptedException, ExecutionException{
long time1=System.currentTimeMillis();
ExecutorService exec = Executors.newCachedThreadPool();
CompletionService<Integer> execcomp = new ExecutorCompletionService<Integer>(exec);
for(int i=0; i<100; i++){
execcomp.submit(getTask());
}
int sum = 0;
for(int i=0; i<100; i++){
//检索并移除表示下一个已完成任务的 Future,如果目前不存在这样的任务,则等待。
Future<Integer> future = execcomp.take();
sum += future.get();
}
long time2=System.currentTimeMillis();
System.out.println("总数为:"+sum);
System.out.println("共耗时:"+(time2-time1));
exec.shutdown();
}
//得到一个任务
public Callable<Integer> getTask(){
final Random rand = new Random();
Callable<Integer> task = new Callable<Integer>(){
@Override
public Integer call() throws Exception {
int i = rand.nextInt(10);
int j = rand.nextInt(10);
int sum = i*j;
System.out.print(sum+"\t");
return sum;
}
};
return task;
}
}
CountDownLatch
package concurrent.CountDownLatch;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
* 从名字可以看出,CountDownLatch是一个倒数计数的锁,当倒数到0时触发事件,也就是开锁,其他人就可以进入了。
* 在一些应用场合中,需要等待某个条件达到要求后才能做后面的事情;同时当线程都完成后也会触发事件,以便进行后面的操作。
* CountDownLatch最重要的方法是countDown()和await(),前者主要是倒数一次,后者是等待倒数到0,如果没有到达0,就只有阻塞等待了。
* 一个CountDouwnLatch实例是不能重复使用的,也就是说它是一次性的,锁一经被打开就不能再关闭使用了,如果想重复使用,请考虑使用CyclicBarrier。
* 下面的例子简单的说明了CountDownLatch的使用方法,模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。
* */
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
// 开始的倒数锁
final CountDownLatch begin = new CountDownLatch(1);
// 结束的倒数锁
final CountDownLatch end = new CountDownLatch(10);
// 十名选手
final ExecutorService exec = Executors.newFixedThreadPool(10);
for (int index = 0; index < 10; index++) {
final int NO = index + 1;
Runnable run = new Runnable() {
public void run() {
try {
begin.await();
Thread.sleep((long) (Math.random() * 10000));
System.out.println("No." + NO + " arrived");
} catch (InterruptedException e) {
} finally {
end.countDown();
}
}
};
exec.submit(run);
}
System.out.println("Game Start");
begin.countDown();
end.await();
System.out.println("Game Over");
exec.shutdown();
}
}
CyclicBarrier
package concurrent.CyclicBarrier;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* CyclicBarrier类似于CountDownLatch也是个计数器,
* 不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数,
* 当线程数达到了CyclicBarrier初始时规定的数目时,所有进入等待状态的线程被唤醒并继续。
* CyclicBarrier就象它名字的意思一样,可看成是个障碍,
* 所有的线程必须到齐后才能一起通过这个障碍。
* CyclicBarrier初始时还可带一个Runnable的参数,
* 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。
*/
class Runner implements Runnable {
private CyclicBarrier barrier;
private String name;
public Runner(CyclicBarrier barrier, String name) {
super();
this.barrier = barrier;
this.name = name;
}
@Override
public void run() {
try {
Thread.sleep(1000 * (new Random()).nextInt(8));
System.out.println(name + " 准备OK.");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(name + " Go!!");
}
}
public class Race {
public static void main(String[] args) throws IOException, InterruptedException {
CyclicBarrier barrier = new CyclicBarrier(3);
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.submit(new Thread(new Runner(barrier, "zhangsan")));
executor.submit(new Thread(new Runner(barrier, "lisi")));
executor.submit(new Thread(new Runner(barrier, "wangwu")));
executor.shutdown();
}
}
Semaphore
package concurrent.Semaphore;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* Semaphore当前在多线程环境下被扩放使用,操作系统的信号量是个很重要的概念,
* 在进程控制方面都有应用。Java 并发库 的Semaphore 可以很轻松完成信号量控制,
* Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,
* 如果没有就等待,而 release() 释放一个许可。
* 比如在Windows下可以设置共享文件的最大客户端访问个数。
*
* Semaphore实现的功能就类似厕所有5个坑,假如有10个人要上厕所,
* 那么同时只能有多少个人去上厕所呢?同时只能有5个人能够占用,
* 当5个人中 的任何一个人让开后,其中等待的另外5个人中又有一个人可以占用了。
* 另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Semaphore对象时传入的参数选项。单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。
*
*/
public class SemaphoreSample {
public static void main(String[] args) {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
// 只能5个线程同时访问
final Semaphore semp = new Semaphore(5);
// 模拟20个客户端访问
for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
// 获取许可
semp.acquire();
System.out.println("Accessing: " + NO);
Thread.sleep((long) (Math.random() * 10000));
// 访问完后,释放
semp.release();
System.out.println("-----------------"+semp.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
exec.execute(run);
}
// 退出线程池
exec.shutdown();
}
}
Exchanger
package concurrent.Exchanger;
import java.util.concurrent.Exchanger;
/**
* 类java.util.concurrent.Exchanger提供了一个同步点, 在这个同步点,一对线程可以交换数据。
* 每个线程通过exchange()方法的入口提供数据给他的伙伴线程, 并接收他的伙伴线程提供的数据,并返回。 当两个线程通过Exchanger交换了对象,
* 这个交换对于两个线程来说都是安全的。
*/
public class ExchangerSample {
public static void main(String args[]) {
Exchanger<String> exgr = new Exchanger<String>();
new UseString(exgr);
new MakeString(exgr);
}
}
class MakeString implements Runnable {
Exchanger<String> ex;
String str;
MakeString(Exchanger<String> c) {
ex = c;
str = new String();
new Thread(this).start();
}
public void run() {
char ch = 'A';
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++)
str += (char) ch++;
try {
str = ex.exchange(str);
} catch (InterruptedException exc) {
System.out.println(exc);
}
}
}
}
class UseString implements Runnable {
Exchanger<String> ex;
String str;
UseString(Exchanger<String> c) {
ex = c;
new Thread(this).start();
}
public void run() {
for (int i = 0; i < 3; i++) {
try {
str = ex.exchange(new String());
System.out.println("Got: " + str);
} catch (InterruptedException exc) {
System.out.println(exc);
}
}
}
}
ReentranLock Condition
package concurrent.reentranLock_condition;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,
* 它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。
* 这就为 Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特性或者锁定语义。
* ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和内存语义,
* 但是添加了类似锁投票、定时锁等候和可中断锁等候的一些特性。
* 此外,它还提供了在激烈争用情况下更佳的性能。
* (换句话说,当许多线程都想访问共享资源时,JVM 可以花更少的时候来调度线程,把更多时间用在执行线程上。)
* reentrant 锁意味着什么呢?简单来说,它有一个与锁相关的获取计数器,如果拥有锁的某个线程再次得到锁,
* 那么获取计数器就加1,然后锁需要被释放两次才能获得真正释放。这模仿了 synchronized 的语义;
* 如果线程进入由线程已经拥有的监控器保护的 synchronized 块,就允许线程继续进行,
* 当线程退出第二个(或者后续) synchronized 块的时候,不释放锁,只有线程退出它进入的监控器保护的第一个 synchronized 块时,才释放锁。
*/
public class ProductQueue<T> {
private final T[] items;
private final Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
private int head, tail, count;
public ProductQueue(int maxSize) {
items = (T[]) new Object[maxSize];
}
public ProductQueue() {
this(10);
}
public void put(T t) throws InterruptedException {
lock.lock();
try {
while (count == getCapacity()) {
notFull.await();
}
items[tail] = t;
if (++tail == getCapacity()) {
tail = 0;
}
++count;
notEmpty.signalAll();
} finally {
lock.unlock();
}
}
public T take() throws InterruptedException {
lock.lock();
try {
while (count == 0) {
notEmpty.await();
}
T ret = items[head];
items[head] = null;//GC
//
if (++head == getCapacity()) {
head = 0;
}
--count;
notFull.signalAll();
return ret;
} finally {
lock.unlock();
}
}
public int getCapacity() {
return items.length;
}
public int size() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
package concurrent.reentranLock_condition;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestCondition {
static final CountDownLatch cdl = new CountDownLatch(31);
public static void main(String[] args) {
Monitor monitor = new Monitor();
ExecutorService executorService = Executors.newFixedThreadPool(31);
for (int i = 0; i < 30; i++) {
Student student = new Student(monitor);
monitor.addClassMate(student);
executorService.execute(student);
}
executorService.execute(monitor);
System.out.println(Thread.currentThread() + "老师还没来");
monitor.setTeacherIsComing(true);
System.out.println(Thread.currentThread() + "老师来了");
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.shutdown();
}
static class Student implements Runnable {
private Monitor monitor;
Student() {
}
Student(Monitor monitor) {
this.monitor = monitor;
}
@Override
public void run() {
try {
monitor.getLock().lock();
while (!monitor.isTeacherIsComing()) {
monitor.getCondition().await();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
monitor.getLock().unlock();
cdl.countDown();
}
System.out.println(Thread.currentThread() + "回到自己座位,坐下");
}
}
static class Monitor extends Student {
private boolean teacherIsComing = false;
private Set<Student> classMates = new HashSet<Student>();
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
@Override
public void run() {
lock.lock();
while (!teacherIsComing) {
System.out.println(Thread.currentThread() + "看老师是否来了");
}
condition.signalAll();
lock.unlock();
cdl.countDown();
}
public boolean isTeacherIsComing() {
return teacherIsComing;
}
public void setTeacherIsComing(boolean teacherIsComing) {
this.teacherIsComing = teacherIsComing;
}
public void addClassMate(Student student) {
classMates.add(student);
}
public Condition getCondition() {
return condition;
}
public Lock getLock() {
return lock;
}
}
}
BlockingQueue
package concurrent.blockingQueue.demo;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class TestBlockingQueues {
public static void main(String[] args) {
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(20);
for (int i = 0; i < 10; i++) {
Thread pro = new Thread(new Producer(queue), "生产者" + i);
pro.start();
}
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new Concumer(queue), "消费者 " + i);
t.start();
}
}
}
class Producer implements Runnable {
BlockingQueue<String> queue;
public Producer(BlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
int i = 0;
while (true) {
try {
System.out.println(Thread.currentThread().getName()
+ "生产食物, 食物编号为:" + Thread.currentThread().getName()
+ i);
queue.put(" 食物 " + Thread.currentThread().getName() + i++);
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("生产者被中断");
}
}
}
}
class Concumer implements Runnable {
BlockingQueue<String> queue;
public Concumer(BlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " 请求消费");
try {
System.out.println(Thread.currentThread().getName() + "消费:"
+ queue.take());
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("消费者被中断");
}
}
}
}