本章涉及内容:
总结:自定义的ForkJoinTask类,同时实现compute的方法
总结:
总结:
日志:
- 自定义ThreadPoolExecutor类
- 实现基于优先级Executor类
- 实现ThreadFactory接口生成自定义线程
- 在Executor对象中使用自定义ThreadFactory
- 在计划线程池运行自定义任务
- 通过实现ThreadFactory接口为Fork/Join框架生成自定义线程
- 在Fork/Join框架运行自定义任务
- 实现自定义锁类
- 基于优先级实现传输队列
- 实现自己的原子对象
1、在Fork/Join框架运行自定义任务
Fork/Join内部存在两种元素;
- 1、一个等待执行的队列任务
- 2、执行队列任务的线程
当然你可以向Fork/Join投入Runnable和Callable接口实现的对象,只是不能利用work-stealing 算法带来的优势。
Fork/Join框架默认两种任务
- 1、RecursiveAction : 任务不会返回值
- 2、RecursiveTask : 任务的将会有返回值。
例子:继承ForkJoinTask任务将会打印执行日志
package com.jack;
import java.util.Date;
import java.util.concurrent.ForkJoinTask;
public abstract class MyWorkerTask extends ForkJoinTask<Void> {
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
public MyWorkerTask(String name) {
super();
this.name = name;
}
@Override
public Void getRawResult() {
return null;
}
@Override
protected void setRawResult(Void value) {
}
@Override
protected boolean exec() {
Date startDate = new Date();
compute();
Date finishDate = new Date();
long diff= finishDate.getTime() - startDate.getTime();
System.out.printf("MyWorkerTask: %s : 花费 %d 秒完成了\n", name, diff);
return true;
}
public String getName() {
return name;
}
protected abstract void compute() ;
}
package com.jack;
public class Task extends MyWorkerTask {
/**
*
*/
private static final long serialVersionUID = 1L;
private int array[];
private int start;
private int end;
public Task(String name, int array[], int start, int end) {
super(name);
this.array =array;
this.start = start;
this.end = end;
}
@Override
protected void compute() {
if(end-start>100){
int mid = (end+start)/2;
Task task1 = new Task(this.getName()+"1", array, start, mid);
Task task2 = new Task(this.getName()+"2", array, mid, end);
invokeAll(task1, task2);
} else {
for (int i=start; i<end; i++){
array[i] ++;
}
try{
Thread.sleep(50);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
总结:自定义的ForkJoinTask类,同时实现compute的方法
package com.jack;
import java.util.concurrent.ForkJoinPool;
public class Main {
public static void main(String[] args) throws Exception{
int array[] = new int[10000];
ForkJoinPool pool = new ForkJoinPool();
Task task = new Task("task", array, 0, array.length);
pool.invoke(task);
pool.shutdown();
System.out.printf("Main: Main方法结束了");
}
}
总结:
- 1、创建长度为10000的数组作为一个任务。
- 2、创建执行任务的ForkJoinPool线程池
- 3、执行任务,关闭线程池。
日志:
扩展:
- 1、setRawResult(): 这个方法是组装任务的结果,如果没有结果就制空
- 2、getRawResult(): 这个方法是返回组装的结果,如果没有就返回null
- 3、exec(): 这个方法实现逻辑的任务,具体的任务可以分配给compute()执行。
2、实现一个自定义锁
lock是java API提供最简单并发处理机制
- lock() : 只要一个线程执行到这里就会锁定这段代码,直到这个线程执行完毕,其他线程才可以执行。
- unlock(): 这个就是解除这个代码的锁定。
默认值实现Lock 的lock类ReentrantLock类
例子:将会实现自己的lock的类
package com.jack;
import java.util.concurrent.TimeUnit;
public class Task implements Runnable {
private MyLock lock;
private String name;
public Task(MyLock lock, String name) {
super();
this.lock = lock;
this.name = name;
}
@Override
public void run() {
lock.lock();
System.out.printf("任务: %s: 获取这个锁\n", name);
try{
TimeUnit.SECONDS.sleep(2);
System.out.printf("任务: %s:释放这个锁\n", name);
} catch (InterruptedException e){
e.printStackTrace();
} finally{
lock.unlock();
}
}
}
package com.jack;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MyLock implements Lock {
private AbstractQueuedSynchronizer sync;
public MyLock() {
super();
sync= new MyAbstractQueuedSynchronizer();
}
@Override
public void lock() {
sync.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
try{
return sync.tryAcquireNanos(1, 1000);
} catch (InterruptedException e){
e.printStackTrace();
return false;
}
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, TimeUnit.NANOSECONDS.convert(time, unit));
}
@Override
public void unlock() {
sync.release(1);
}
@Override
public Condition newCondition() {
return sync.new ConditionObject();
}
}
package com.jack;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
public class MyAbstractQueuedSynchronizer extends
AbstractQueuedSynchronizer{
/**
*
*/
private static final long serialVersionUID = 1L;
private AtomicInteger state;
public MyAbstractQueuedSynchronizer() {
super();
this.state = new AtomicInteger(0);
}
@Override
protected boolean tryAcquire(int arg) {
return state.compareAndSet(0,1);
}
@Override
protected boolean tryRelease(int arg) {
return state.compareAndSet(1, 0);
}
}
package com.jack;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws Exception{
MyLock lock = new MyLock();
for (int i=0; i<10; i++){
Task task = new Task(lock, "任务一" + i);
Thread thread = new Thread(task);
thread.start();
}
boolean value;
do{
try{
value = lock.tryLock(1, TimeUnit.SECONDS);
if(!value){
System.out.printf("Main: 尝试获取这个锁\n");
}
}catch (InterruptedException e){
e.printStackTrace();
value = false;
}
}while (!value);
System.out.printf("Main: 获取到这个锁\n");
lock.unlock();
System.out.printf("Main: 执行完成了");
}
}
日志:
任务: 任务一0: 获取这个锁
Main: 尝试获取这个锁
Main: 尝试获取这个锁
任务: 任务一0:释放这个锁
任务: 任务一1: 获取这个锁
Main: 尝试获取这个锁
Main: 尝试获取这个锁
任务: 任务一1:释放这个锁
任务: 任务一2: 获取这个锁
Main: 尝试获取这个锁
Main: 尝试获取这个锁
任务: 任务一2:释放这个锁
任务: 任务一3: 获取这个锁
Main: 尝试获取这个锁
Main: 尝试获取这个锁
任务: 任务一3:释放这个锁
任务: 任务一4: 获取这个锁
Main: 尝试获取这个锁
Main: 尝试获取这个锁
任务: 任务一4:释放这个锁
任务: 任务一5: 获取这个锁
Main: 尝试获取这个锁
Main: 尝试获取这个锁
任务: 任务一5:释放这个锁
任务: 任务一6: 获取这个锁
Main: 尝试获取这个锁
Main: 尝试获取这个锁
任务: 任务一6:释放这个锁
任务: 任务一7: 获取这个锁
Main: 尝试获取这个锁
Main: 尝试获取这个锁
任务: 任务一7:释放这个锁
任务: 任务一8: 获取这个锁
Main: 尝试获取这个锁
Main: 尝试获取这个锁
任务: 任务一8:释放这个锁
任务: 任务一9: 获取这个锁
Main: 尝试获取这个锁
Main: 尝试获取这个锁
任务: 任务一9:释放这个锁
Main: 获取到这个锁
Main: 执行完成了
总结:
- 1、MyAbstractQueuedSynchronizer改变锁的状态(类似小区门口指示牌,当前是否有空位,如果出去一辆就有空位了,空位数据加1,反之减一)
- 2、Mylock实现lock,锁定的状态为1,释放为0(也就是只要状态为0,表示这段代码可以被其他线程使用)
3、基于优先级实现传输队列
Java API提供几种数据结构去实现并发:如下介绍两种
LinkedTransferQueue: 链表式传输队列,它可以用于生产者/消费者模型。它遵循FIFO,如果一方没有将会阻塞。
PriorityBlockingQueue: 这个基于优先级传输队列,就是贵宾(不是贵宾犬)优先。
例子;实现生产者和消费者模型
package com.jack;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TransferQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
public class MyPriorityTransferQueue<E> extends PriorityBlockingQueue<E>
implements TransferQueue<E>{
/**
*
*/
private static final long serialVersionUID = 1L;
private AtomicInteger counter;
private LinkedBlockingQueue<E> transfered;
private ReentrantLock lock;
public MyPriorityTransferQueue() {
super();
this.counter = new AtomicInteger(0);
this.transfered = new LinkedBlockingQueue<E>();
this.lock = new ReentrantLock();
}
@Override
public boolean tryTransfer(E e) {
lock.lock();
boolean value;
if(counter.get() ==0){
value=false;
} else {
put(e);
value=true;
}
lock.unlock();
return value;
}
@Override
public void transfer(E e) throws InterruptedException {
lock.lock();
if(counter.get() !=0){
put(e);
lock.unlock();
} else {
transfered.add(e);
lock.unlock();
synchronized (e) {
e.wait();
}
}
}
@Override
public boolean tryTransfer(E e, long timeout, TimeUnit unit) throws InterruptedException {
lock.lock();
if(counter.get()!=0){
put(e);
lock.unlock();
return true;
} else {
transfered.add(e);
long newTimeout = TimeUnit.MILLISECONDS.convert(timeout, unit);
lock.unlock();
e.wait(newTimeout);
lock.lock();
if(transfered.contains(e)){
transfered.remove(e);
lock.unlock();
return false;
} else {
lock.unlock();
return true;
}
}
}
@Override
public boolean hasWaitingConsumer() {
return (counter.get()!=0);
}
@Override
public int getWaitingConsumerCount() {
return counter.get();
}
@Override
public E take() throws InterruptedException {
lock.lock();
counter.incrementAndGet();
E value = transfered.poll();
if(value ==null){
lock.unlock();
value=super.take();
lock.lock();
} else {
synchronized (value) {
value.notify();
}
}
counter.decrementAndGet();
lock.unlock();
return value;
}
}
package com.jack;
public class Event implements Comparable<Event>{
private String thread;
private int priority;
public Event(String thread, int priority) {
super();
this.thread = thread;
this.priority = priority;
}
public String getThread() {
return thread;
}
public int getPriority() {
return priority;
}
@Override
public int compareTo(Event o) {
if(this.priority>o.getPriority()){
return -1;
} else if(this.priority<o.getPriority()){
return 1;
}
return 0;
}
}
package com.jack;
public class Producer implements Runnable{
private MyPriorityTransferQueue<Event> buffer;
public Producer(MyPriorityTransferQueue<Event> buffer) {
super();
this.buffer = buffer;
}
@Override
public void run() {
for (int i=0; i<100; i++){
Event event = new Event(Thread.currentThread().getName(), i);
buffer.put(event);
System.out.printf("生产者:%s: 优先级:%d\n", event.getThread(), event.getPriority());
}
}
}
package com.jack;
public class Consumer implements Runnable{
private MyPriorityTransferQueue<Event> buffer;
public Consumer(MyPriorityTransferQueue<Event> buffer) {
super();
this.buffer = buffer;
}
@Override
public void run() {
for(int i=0; i<1002; i++){
try{
Event value = buffer.take();
System.out.printf("消费者:%s: 优先级:%d\n", value.getThread(), value.getPriority());
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
package com.jack;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws Exception{
MyPriorityTransferQueue<Event> buffer = new MyPriorityTransferQueue<Event>();
Producer producer = new Producer(buffer);
Thread producerThreads[] = new Thread[10];
for (int i=0; i<producerThreads.length; i++){
producerThreads[i] = new Thread(producer);
producerThreads[i].start();
}
Consumer consumer = new Consumer(buffer);
Thread consumerThread = new Thread(consumer);
consumerThread.start();
System.out.printf("Main: Buffer: 消费数量:%d\n", buffer.getWaitingConsumerCount());
Event myEvent = new Event("核心事务1", 0);
buffer.transfer(myEvent);
System.out.printf("Main: 事件已经传输了.\n");
for (int i=0; i<producerThreads.length; i++){
try {
producerThreads[i].join();
}catch (InterruptedException e){
e.printStackTrace();
}
}
TimeUnit.SECONDS.sleep(1);
System.out.printf("Main: Buffer: 消费数量: %d\n", buffer.getWaitingConsumerCount());
myEvent = new Event("核心事件 2", 0);
buffer.transfer(myEvent);
consumerThread.join();
System.out.println("Main:执行完毕");
}
}
总结:
- 1、继承了PriorityBlockingQueue类,实现了TransferQueue完成插入元素操作,这些方法都关联生产者消费者
4、实现你自己的原子对象
package com.jack;
import java.util.concurrent.atomic.AtomicInteger;
public class ParkingCounter extends AtomicInteger{
/**
*
*/
private static final long serialVersionUID = 1L;
private int maxNumber;
public ParkingCounter(int maxNumber){
set(0);
this.maxNumber = maxNumber;
}
public boolean carIn(){
for(;;){
int value = get();
if(value==maxNumber){
System.out.printf("ParingCounter: 停车场已满了\n");
return false;
} else {
int newValue = value+1;
boolean changed = compareAndSet(value,newValue);
if(changed){
System.out.printf("ParkingCounter: 一辆车已经进入了\n");
return true;
}
}
}
}
public boolean carOut(){
for(;;){
int value = get();
if(value==0){
System.out.printf("ParkingCounter: 停车场已经空了\n");
return false;
}else {
int newValue = value-1;
boolean changed = compareAndSet(value, newValue);
if(changed){
System.out.printf("ParkingCounter: 一辆车已经使出了\n");
return true;
}
}
}
}
}
package com.jack;
public class Sensor1 implements Runnable{
private ParkingCounter counter;
public Sensor1(ParkingCounter counter) {
super();
this.counter = counter;
}
@Override
public void run() {
counter.carIn();
counter.carIn();
counter.carIn();
counter.carIn();
counter.carIn();
counter.carOut();
counter.carOut();
counter.carOut();
counter.carOut();
counter.carIn();
counter.carIn();
counter.carIn();
}
}
package com.jack;
public class Sensor2 implements Runnable{
private ParkingCounter counter;
public Sensor2(ParkingCounter counter) {
super();
this.counter = counter;
}
@Override
public void run() {
counter.carIn();
counter.carOut();
counter.carOut();
counter.carOut();
counter.carOut();
counter.carIn();
counter.carIn();
counter.carIn();
counter.carOut();
}
}
package com.jack;
public class Main {
public static void main(String[] args) throws Exception{
ParkingCounter counter = new ParkingCounter(5);
Sensor1 sensor1 = new Sensor1(counter);
Sensor2 sensor2 = new Sensor2(counter);
Thread thread1 = new Thread(sensor1);
Thread thread2 = new Thread(sensor2);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.printf("Main: 停车场还剩多少车:%d\n", counter.get());
System.out.println("Main:执行结束");
}
}
日志:
ParkingCounter: 一辆车已经进入了
ParkingCounter: 一辆车已经进入了
ParkingCounter: 一辆车已经进入了
ParkingCounter: 一辆车已经进入了
ParingCounter: 停车场已满了
ParkingCounter: 一辆车已经进入了
ParkingCounter: 一辆车已经使出了
ParkingCounter: 一辆车已经使出了
ParkingCounter: 一辆车已经使出了
ParkingCounter: 一辆车已经使出了
ParkingCounter: 停车场已经空了
ParkingCounter: 一辆车已经进入了
ParkingCounter: 一辆车已经进入了
ParkingCounter: 一辆车已经进入了
ParkingCounter: 一辆车已经使出了
ParkingCounter: 一辆车已经使出了
ParkingCounter: 一辆车已经使出了
ParkingCounter: 一辆车已经进入了
ParkingCounter: 一辆车已经进入了
ParkingCounter: 一辆车已经进入了
ParkingCounter: 一辆车已经使出了
Main: 停车场还剩多少车:3
Main:执行结束
第七章完。。。
参考《Java 7 Concurrency Cookbook》