├── notes ├── README.md ├── ch1.md ├── ch7.md ├── ch2.md ├── ch5.md ├── ch4.md ├── ch6.md └── ch3.md ├── src └── main │ └── java │ ├── ch7 │ ├── s2 │ │ ├── samplehello.conf │ │ ├── Greeter.java │ │ ├── HelloMainSimple.java │ │ └── HelloWorld.java │ ├── s3 │ │ └── ImmutableMessage.java │ └── s4 │ │ ├── DeadMain.java │ │ ├── WatchActor.java │ │ └── MyWorker.java │ ├── ch5 │ ├── s5 │ │ ├── s2 │ │ │ ├── Data.java │ │ │ ├── Client.java │ │ │ ├── Main.java │ │ │ ├── RealData.java │ │ │ └── FutureData.java │ │ └── s3 │ │ │ ├── RealData.java │ │ │ └── FutureMain.java │ ├── s6 │ │ ├── Msg.java │ │ ├── Multiply.java │ │ ├── PStreamMain.java │ │ ├── Div.java │ │ └── Plus.java │ ├── s4 │ │ ├── PCData.java │ │ ├── PCDataFactory.java │ │ ├── Consumer.java │ │ ├── Producer.java │ │ ├── FalseSharing.java │ │ └── Main.java │ ├── s1 │ │ ├── Singleton.java │ │ ├── LazySingleton.java │ │ └── StaticSingleton.java │ ├── s3 │ │ ├── PCData.java │ │ ├── Consumer.java │ │ ├── Main.java │ │ └── Producer.java │ ├── s2 │ │ └── Product.java │ └── s7 │ │ └── Main.java │ ├── ch6 │ ├── s2 │ │ ├── IAnimal.java │ │ ├── IHorse.java │ │ ├── IDonkey.java │ │ ├── BadMethodRef.java │ │ ├── Mule.java │ │ ├── Example1.java │ │ ├── InstanceMethodRef.java │ │ └── ConstrMethodRef.java │ ├── s1 │ │ ├── Example2.java │ │ ├── Example3.java │ │ └── Example1.java │ ├── s5 │ │ ├── Example5.java │ │ ├── Example2.java │ │ ├── Example6.java │ │ ├── Example3.java │ │ ├── Example4.java │ │ └── Example1.java │ ├── s4 │ │ └── PrimeUtil.java │ ├── s7 │ │ └── LongAccumulatorDemo.java │ └── s6 │ │ ├── Point.java │ │ └── StampedLockCPUDemo.java │ ├── ch2 │ ├── JoinMain.java │ ├── NoVisibility.java │ ├── DeamonDemo.java │ ├── AccountingSyncBad.java │ ├── ThreadGroupName.java │ ├── BadSuspend.java │ ├── AccountingVol.java │ ├── PriorityDemo.java │ └── SimpleWN.java │ ├── ch3 │ ├── s2 │ │ ├── ScheduledExecutorServiceDemo.java │ │ ├── ThreadPoolDemo.java │ │ ├── RejectThreadPoolDemo.java │ │ ├── MyThreadFactory.java │ │ ├── ExtThreadPool.java │ │ ├── TraceThreadPoolExecutor.java │ │ └── CountTask.java │ └── s1 │ │ ├── FairLock.java │ │ ├── SemapDemo.java │ │ ├── ReenterLock.java │ │ ├── TimeLock.java │ │ ├── LockSupportDemo.java │ │ ├── ReenterLockCondition.java │ │ ├── CountDownLatchDemo.java │ │ ├── LockSupportIntDemo.java │ │ ├── IntLock.java │ │ ├── CyclicBarrierDemo.java │ │ ├── ReadWriteLockDemo.java │ │ └── TryLock.java │ ├── ch4 │ ├── s4 │ │ ├── AtomicIntegerDemo.java │ │ ├── AtomicIntegerArrayDemo.java │ │ ├── AtomicIntegerFieldUpdaterDemo.java │ │ ├── AtomicReferenceDemo.java │ │ └── AtomicStampedReferenceDemo.java │ ├── s3 │ │ ├── ThreadLocalDemo.java │ │ ├── WeakVsHashMap.java │ │ ├── ThreadLocalPerformance.java │ │ └── ThreadLocalDemo_Gc.java │ └── s5 │ │ └── DeadLock.java │ └── ch1 │ └── MultiThreadLong.java ├── .gitignore ├── LICENSE ├── pom.xml └── README.md /notes/README.md: -------------------------------------------------------------------------------- 1 | 这里包含了所有章节的笔记和对应代码目录,如有错误,欢迎指出 -------------------------------------------------------------------------------- /src/main/java/ch7/s2/samplehello.conf: -------------------------------------------------------------------------------- 1 | akka { 2 | loglevel = INFO 3 | } -------------------------------------------------------------------------------- /src/main/java/ch5/s5/s2/Data.java: -------------------------------------------------------------------------------- 1 | package ch5.s5.s2; 2 | 3 | public interface Data { 4 | public String getResult(); 5 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | out 3 | 4 | ### IntelliJ IDEA ### 5 | .idea 6 | *.iws 7 | *.iml 8 | *.ipr 9 | 10 | target 11 | 12 | -------------------------------------------------------------------------------- /src/main/java/ch5/s6/Msg.java: -------------------------------------------------------------------------------- 1 | package ch5.s6; 2 | 3 | public class Msg { 4 | public double i; 5 | public double j; 6 | public String orgStr=null; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/ch6/s2/IAnimal.java: -------------------------------------------------------------------------------- 1 | package ch6.s2; 2 | 3 | public interface IAnimal { 4 | default void breath(){ 5 | System.out.println("breath"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/ch6/s2/IHorse.java: -------------------------------------------------------------------------------- 1 | package ch6.s2; 2 | 3 | public interface IHorse { 4 | void eat(); 5 | default void run(){ 6 | System.out.println("hourse run"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/ch6/s2/IDonkey.java: -------------------------------------------------------------------------------- 1 | package ch6.s2; 2 | 3 | public interface IDonkey { 4 | void eat(); 5 | default void run(){ 6 | System.out.println("Donkey run"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/ch5/s4/PCData.java: -------------------------------------------------------------------------------- 1 | package ch5.s4; 2 | 3 | public class PCData { 4 | public long get() { 5 | return value; 6 | } 7 | 8 | public void set(long value) { 9 | this.value = value; 10 | } 11 | 12 | private long value; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ch5/s4/PCDataFactory.java: -------------------------------------------------------------------------------- 1 | package ch5.s4; 2 | 3 | import com.lmax.disruptor.EventFactory; 4 | 5 | public class PCDataFactory implements EventFactory { 6 | @Override 7 | public PCData newInstance() { 8 | return new PCData(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/ch5/s1/Singleton.java: -------------------------------------------------------------------------------- 1 | package ch5.s1; 2 | 3 | public class Singleton { 4 | private Singleton(){ 5 | System.out.println("Singleton is created"); 6 | } 7 | private static Singleton instance = new Singleton(); 8 | public static Singleton getInstance(){ 9 | return instance; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/ch5/s4/Consumer.java: -------------------------------------------------------------------------------- 1 | package ch5.s4; 2 | 3 | import com.lmax.disruptor.WorkHandler; 4 | 5 | public class Consumer implements WorkHandler { 6 | public void onEvent(PCData event) throws Exception { 7 | System.out.println(Thread.currentThread().getId() + ":Event: --" + event.get() * event.get() + "--"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/ch6/s1/Example2.java: -------------------------------------------------------------------------------- 1 | package ch6.s1; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Example2 { 6 | public static void main(String[] args){ 7 | int[] arr={1,3,4,5,6,7,8,9,10}; 8 | Arrays.stream(arr).map((x)->x=x+1).forEach(System.out::println); 9 | System.out.println(); 10 | Arrays.stream(arr).forEach(System.out::println); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/ch5/s1/LazySingleton.java: -------------------------------------------------------------------------------- 1 | package ch5.s1; 2 | 3 | public class LazySingleton { 4 | private LazySingleton() { 5 | System.out.println("LazySingleton is created"); 6 | } 7 | 8 | private static LazySingleton instance = null; 9 | 10 | public static synchronized LazySingleton getInstance() { 11 | if (instance == null) 12 | instance = new LazySingleton(); 13 | return instance; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/ch5/s5/s2/Client.java: -------------------------------------------------------------------------------- 1 | package ch5.s5.s2; 2 | 3 | public class Client { 4 | public Data request(final String queryStr){ 5 | final FutureData future = new FutureData(); 6 | new Thread(){ 7 | public void run(){ 8 | RealData realdata = new RealData(queryStr); 9 | future.setRealData(realdata); 10 | } 11 | }.start(); 12 | return future; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ch5/s3/PCData.java: -------------------------------------------------------------------------------- 1 | package ch5.s3; 2 | 3 | public class PCData { 4 | private final int intData; 5 | 6 | public PCData(int d) { 7 | intData = d; 8 | } 9 | 10 | public PCData(String d) { 11 | intData = Integer.valueOf(d); 12 | } 13 | 14 | public int getData() { 15 | return intData; 16 | } 17 | 18 | 19 | public String toString() { 20 | return "data=" + intData; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ch6/s2/BadMethodRef.java: -------------------------------------------------------------------------------- 1 | package ch6.s2; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class BadMethodRef { 7 | public static void main(String []args){ 8 | List numbers=new ArrayList(); 9 | for(int i=1;i<10;i++){ 10 | numbers.add(Double.valueOf(i)); 11 | } 12 | // numbers.stream().map(Double::toString).forEach(System.out::println); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ch6/s2/Mule.java: -------------------------------------------------------------------------------- 1 | package ch6.s2; 2 | 3 | public class Mule implements IHorse,IDonkey,IAnimal { 4 | 5 | @Override 6 | public void eat() { 7 | System.out.println("Mule eat"); 8 | } 9 | 10 | @Override 11 | public void run() { 12 | IHorse.super.run(); 13 | } 14 | 15 | public static void main(String[] args){ 16 | Mule m =new Mule(); 17 | m.run(); 18 | m.breath(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ch5/s1/StaticSingleton.java: -------------------------------------------------------------------------------- 1 | package ch5.s1; 2 | 3 | public class StaticSingleton { 4 | private StaticSingleton(){ 5 | System.out.println("StaticSingleton is created"); 6 | } 7 | // 内部类没被调用前不会被加载 8 | private static class SingletonHolder{ 9 | private static StaticSingleton instance = new StaticSingleton(); 10 | } 11 | public static StaticSingleton getInstance(){ 12 | return SingletonHolder.instance; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ch5/s5/s2/Main.java: -------------------------------------------------------------------------------- 1 | package ch5.s5.s2; 2 | 3 | public class Main { 4 | public static void main(String[] args){ 5 | Client client = new Client(); 6 | Data data = client.request("name"); 7 | System.out.println("请求完毕"); 8 | try { 9 | Thread.sleep(2000); 10 | } catch (InterruptedException e) { 11 | e.printStackTrace(); 12 | } 13 | System.out.println("数据 = " + data.getResult()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/ch6/s1/Example3.java: -------------------------------------------------------------------------------- 1 | package ch6.s1; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Example3 { 6 | public static void main(String[] args){ 7 | int[] arr={1,3,4,5,6,7,8,9,10}; 8 | for(int i=0;i(x%2==0?x:x+1)).forEach(System.out::println); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/ch7/s2/Greeter.java: -------------------------------------------------------------------------------- 1 | package ch7.s2; 2 | 3 | import akka.actor.UntypedActor; 4 | 5 | public class Greeter extends UntypedActor { 6 | public static enum Msg{ 7 | GREET, DONE; 8 | } 9 | @Override 10 | public void onReceive(Object msg) { 11 | if(msg == Msg.GREET){ 12 | System.out.println("Hello World!"); 13 | getSender().tell(Msg.DONE, getSelf()); 14 | }else{ 15 | unhandled(msg); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ch2/JoinMain.java: -------------------------------------------------------------------------------- 1 | package ch2; 2 | 3 | public class JoinMain { 4 | public static volatile int i = 0; 5 | 6 | public static class AddThread extends Thread{ 7 | 8 | 9 | public void run() { 10 | for(i=0;i<10000000;i++){ 11 | } 12 | } 13 | } 14 | 15 | public static void main(String[] args) throws InterruptedException { 16 | AddThread at = new AddThread(); 17 | at.start(); 18 | at.join(); 19 | System.out.println(i); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/ch7/s2/HelloMainSimple.java: -------------------------------------------------------------------------------- 1 | package ch7.s2; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.ActorSystem; 5 | import akka.actor.Props; 6 | import com.typesafe.config.ConfigFactory; 7 | 8 | public class HelloMainSimple { 9 | public static void main(String[] args){ 10 | ActorSystem system = ActorSystem.create("Hello",ConfigFactory.load("samplehello.conf")); 11 | ActorRef a =system.actorOf(Props.create(HelloWorld.class),"helloWorld"); 12 | System.out.println("HelloWorld Actor Path:" + a.path()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/ch5/s5/s3/RealData.java: -------------------------------------------------------------------------------- 1 | package ch5.s5.s3; 2 | 3 | import java.util.concurrent.Callable; 4 | 5 | public class RealData implements Callable { 6 | private String para; 7 | public RealData(String para) { 8 | this.para = para; 9 | } 10 | 11 | @Override 12 | public String call() throws Exception { 13 | StringBuffer sb = new StringBuffer(); 14 | for(int i=0;i<10;i++){ 15 | sb.append(para); 16 | Thread.sleep(100); 17 | } 18 | return sb.toString(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ch6/s2/Example1.java: -------------------------------------------------------------------------------- 1 | package ch6.s2; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.function.Function; 6 | 7 | public class Example1 { 8 | static final int num =2; 9 | public static void main(String[] args) { 10 | List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); 11 | numbers.forEach((Integer value) -> System.out.println(value)); 12 | 13 | Function stringConverter = (from) ->from * num; 14 | System.out.println(stringConverter.apply(3)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/ch5/s2/Product.java: -------------------------------------------------------------------------------- 1 | package ch5.s2; 2 | 3 | public final class Product { 4 | private final String no; 5 | private final String name; 6 | private final double price; 7 | 8 | public Product(String no, String name, double price) { 9 | this.no = no; 10 | this.name = name; 11 | this.price = price; 12 | } 13 | 14 | public String getNo() { 15 | return no; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public double getPrice() { 23 | return price; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ch6/s1/Example1.java: -------------------------------------------------------------------------------- 1 | package ch6.s1; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Example1 { 6 | public static void imperative(){ 7 | int[] iArr={1,3,4,5,6,9,8,7,4,2}; 8 | for(int i=0;i bq = new LinkedBlockingQueue(); 8 | @Override 9 | public void run() { 10 | while(true){ 11 | try { 12 | Msg msg = bq.take(); 13 | msg.i = msg.i *msg.j; 14 | Div.bq.add(msg); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ch5/s6/PStreamMain.java: -------------------------------------------------------------------------------- 1 | package ch5.s6; 2 | 3 | public class PStreamMain { 4 | public static void main(String[] args) { 5 | new Thread(new Plus()).start(); 6 | new Thread(new Multiply()).start(); 7 | new Thread(new Div()).start(); 8 | 9 | for (int i = 1; i <= 1000; i++) { 10 | for (int j = 1; j <= 1000; j++) { 11 | Msg msg = new Msg(); 12 | msg.i = i; 13 | msg.j = j; 14 | msg.orgStr = "((" + i + "+" + j + ")*" + i + ")/2"; 15 | Plus.bq.add(msg); 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ch5/s5/s2/RealData.java: -------------------------------------------------------------------------------- 1 | package ch5.s5.s2; 2 | 3 | public class RealData implements Data{ 4 | protected final String result; 5 | 6 | public RealData(String para) { 7 | StringBuffer sb = new StringBuffer(); 8 | for(int i=0;i<10;i++){ 9 | sb.append(para); 10 | try { 11 | Thread.sleep(100); 12 | } catch (InterruptedException e) { 13 | e.printStackTrace(); 14 | } 15 | } 16 | result = sb.toString(); 17 | } 18 | 19 | @Override 20 | public String getResult() { 21 | return result; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ch5/s4/Producer.java: -------------------------------------------------------------------------------- 1 | package ch5.s4; 2 | 3 | import com.lmax.disruptor.RingBuffer; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | public class Producer { 8 | private final RingBuffer ringBuffer; 9 | 10 | public Producer(RingBuffer ringBuffer) { 11 | this.ringBuffer = ringBuffer; 12 | } 13 | 14 | public void pushData(ByteBuffer bb){ 15 | long sequence = ringBuffer.next(); 16 | try{ 17 | PCData event = ringBuffer.get(sequence); 18 | event.set(bb.getLong(0)); 19 | }finally { 20 | ringBuffer.publish(sequence); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ch5/s6/Div.java: -------------------------------------------------------------------------------- 1 | package ch5.s6; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.concurrent.LinkedBlockingQueue; 5 | 6 | public class Div implements Runnable { 7 | public static BlockingQueue bq= new LinkedBlockingQueue(); 8 | @Override 9 | public void run() { 10 | while(true){ 11 | try { 12 | Msg msg = bq.take(); 13 | msg.i = msg.i / 2; 14 | System.out.println(msg.orgStr + "=" + msg.i); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ch2/NoVisibility.java: -------------------------------------------------------------------------------- 1 | package ch2; 2 | 3 | public class NoVisibility { 4 | // private static boolean ready; 5 | private static volatile boolean ready; 6 | private static int number; 7 | 8 | private static class ReaderThread extends Thread{ 9 | 10 | 11 | public void run() { 12 | while(!ready); 13 | System.out.println(number); 14 | } 15 | } 16 | 17 | public static void main(String[] args) throws InterruptedException { 18 | new ReaderThread().start(); 19 | Thread.sleep(1000); 20 | number = 42; 21 | ready = true; 22 | Thread.sleep(1000); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ch5/s6/Plus.java: -------------------------------------------------------------------------------- 1 | package ch5.s6; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.concurrent.LinkedBlockingDeque; 5 | 6 | public class Plus implements Runnable { 7 | public static BlockingQueue bq = new LinkedBlockingDeque(); 8 | 9 | @Override 10 | public void run() { 11 | while (true) { 12 | Msg msg = null; 13 | try { 14 | msg = bq.take(); 15 | msg.j = msg.i + msg.j; 16 | Multiply.bq.add(msg); 17 | } catch (InterruptedException e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ch6/s5/Example5.java: -------------------------------------------------------------------------------- 1 | package ch6.s5; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.ExecutionException; 5 | 6 | public class Example5 { 7 | public static Integer calc(Integer para){ 8 | return para/2; 9 | } 10 | 11 | public static void main(String []args) throws ExecutionException, InterruptedException { 12 | CompletableFuture fu = CompletableFuture.supplyAsync(()->calc(50)) 13 | .thenCompose((i)->CompletableFuture.supplyAsync(()->calc(i))) 14 | .thenApply((str)->"\""+str+"\"") 15 | .thenAccept(System.out::println); 16 | fu.get(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ch6/s5/Example2.java: -------------------------------------------------------------------------------- 1 | package ch6.s5; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.ExecutionException; 5 | 6 | public class Example2 { 7 | public static Integer calc(Integer para){ 8 | try{ 9 | Thread.sleep(1000); 10 | } catch (InterruptedException e) { 11 | e.printStackTrace(); 12 | } 13 | return para * para; 14 | } 15 | 16 | public static void main(String[] args) throws ExecutionException, InterruptedException { 17 | final CompletableFuture future = CompletableFuture.supplyAsync(()->calc(50)); 18 | System.out.println(future.get()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/ch7/s3/ImmutableMessage.java: -------------------------------------------------------------------------------- 1 | package ch7.s3; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | public class ImmutableMessage { 8 | private final int sequenceNumber; 9 | 10 | private final List values; 11 | 12 | public ImmutableMessage(int sequenceNumber, List values) { 13 | this.sequenceNumber = sequenceNumber; 14 | this.values = Collections.unmodifiableList(new ArrayList(values)); 15 | } 16 | 17 | public int getSequenceNumber() { 18 | return sequenceNumber; 19 | } 20 | 21 | public List getValues() { 22 | return values; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/ch2/DeamonDemo.java: -------------------------------------------------------------------------------- 1 | package ch2; 2 | 3 | public class DeamonDemo { 4 | 5 | public static class DeamonT extends Thread{ 6 | 7 | 8 | public void run() { 9 | while (true){ 10 | System.out.println("I am alive"); 11 | try { 12 | Thread.sleep(1000); 13 | } catch (InterruptedException e) { 14 | e.printStackTrace(); 15 | } 16 | } 17 | } 18 | } 19 | 20 | public static void main(String[] args) throws InterruptedException { 21 | Thread t = new DeamonT(); 22 | t.setDaemon(true); 23 | t.start(); 24 | Thread.sleep(2000); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ch5/s5/s2/FutureData.java: -------------------------------------------------------------------------------- 1 | package ch5.s5.s2; 2 | 3 | public class FutureData implements Data { 4 | protected RealData realData = null; 5 | protected boolean isReady = false; 6 | 7 | public synchronized void setRealData(RealData realData) { 8 | if(isReady){ 9 | return; 10 | } 11 | this.realData = realData; 12 | isReady = true; 13 | notifyAll(); 14 | } 15 | 16 | @Override 17 | public synchronized String getResult() { 18 | while (!isReady){ 19 | try { 20 | wait(); 21 | } catch (InterruptedException e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | return realData.result; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ch6/s4/PrimeUtil.java: -------------------------------------------------------------------------------- 1 | package ch6.s4; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | public class PrimeUtil { 6 | public static boolean isPrime(int number){ 7 | int tmp = number; 8 | if (tmp<2){ 9 | return false; 10 | } 11 | for(int i=2;Math.sqrt(tmp)>=i;i++){ 12 | if(tmp%i==0){ 13 | return false; 14 | } 15 | } 16 | return true; 17 | } 18 | 19 | public static void main(String[]args){ 20 | long sum = IntStream.range(1, 1000000).filter(PrimeUtil::isPrime).count(); 21 | System.out.println(sum); 22 | 23 | sum = IntStream.range(1, 1000000).parallel().filter(PrimeUtil::isPrime).count(); 24 | System.out.println(sum); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ch7/s4/DeadMain.java: -------------------------------------------------------------------------------- 1 | package ch7.s4; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.ActorSystem; 5 | import akka.actor.PoisonPill; 6 | import akka.actor.Props; 7 | import com.typesafe.config.ConfigFactory; 8 | 9 | public class DeadMain { 10 | public static void main(String[] args){ 11 | ActorSystem system = ActorSystem.create("deadwatch", ConfigFactory.load("samplehello.conf")); 12 | ActorRef worker = system.actorOf(Props.create(MyWorker.class), "worker"); 13 | system.actorOf(Props.create(WatchActor.class, worker), "watcher"); 14 | worker.tell(MyWorker.Msg.WORKING, ActorRef.noSender()); 15 | worker.tell(MyWorker.Msg.DONE, ActorRef.noSender()); 16 | worker.tell(PoisonPill.getInstance(), ActorRef.noSender()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/ch6/s5/Example6.java: -------------------------------------------------------------------------------- 1 | package ch6.s5; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.ExecutionException; 5 | 6 | public class Example6 { 7 | public static Integer calc(Integer para){ 8 | return para/2; 9 | } 10 | 11 | public static void main(String []args) throws ExecutionException, InterruptedException { 12 | CompletableFuture intFuture = CompletableFuture.supplyAsync(()->calc(50)); 13 | CompletableFuture intFuture2 = CompletableFuture.supplyAsync(()->calc(25)); 14 | CompletableFuture fu = intFuture.thenCombine(intFuture2,(i,j)->(i+j)) 15 | .thenApply((str)->"\""+str+"\"") 16 | .thenAccept(System.out::println); 17 | fu.get(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/ch6/s2/InstanceMethodRef.java: -------------------------------------------------------------------------------- 1 | package ch6.s2; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class InstanceMethodRef { 7 | 8 | static class User{ 9 | private int num; 10 | private String name; 11 | 12 | public User(int num, String name) { 13 | this.num = num; 14 | this.name = name; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | } 21 | 22 | public static void main(String[] args){ 23 | List users=new ArrayList(); 24 | for(int i=1;i<10;i++){ 25 | users.add(new User(i,"billy"+Integer.toString(i))); 26 | } 27 | users.stream().map(User::getName).forEach(System.out::println); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ch6/s5/Example3.java: -------------------------------------------------------------------------------- 1 | package ch6.s5; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.ExecutionException; 5 | 6 | public class Example3 { 7 | public static Integer calc(Integer para){ 8 | try{ 9 | Thread.sleep(1000); 10 | } catch (InterruptedException e) { 11 | e.printStackTrace(); 12 | } 13 | return para * para; 14 | } 15 | 16 | public static void main(String []args) throws ExecutionException, InterruptedException { 17 | CompletableFuture fu=CompletableFuture.supplyAsync(()->calc(50)) 18 | .thenApply((i)->Integer.toString(i)) 19 | .thenApply((str)->"\""+str+"\"") 20 | .thenAccept(System.out::println); 21 | fu.get(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ch7/s2/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package ch7.s2; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Props; 5 | import akka.actor.UntypedActor; 6 | 7 | public class HelloWorld extends UntypedActor { 8 | ActorRef greeter; 9 | 10 | @Override 11 | public void preStart() { 12 | greeter = getContext().actorOf(Props.create(Greeter.class), "greeter"); 13 | System.out.println("Greeter Actor Path:" + greeter.path()); 14 | greeter.tell(Greeter.Msg.GREET, getSelf()); 15 | } 16 | 17 | @Override 18 | public void onReceive(Object msg) throws Exception { 19 | if(msg == Greeter.Msg.DONE){ 20 | greeter.tell(Greeter.Msg.GREET, getSelf()); 21 | getContext().stop(getSelf()); 22 | }else{ 23 | unhandled(msg); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ch3/s2/ScheduledExecutorServiceDemo.java: -------------------------------------------------------------------------------- 1 | package ch3.s2; 2 | 3 | import java.util.concurrent.Executors; 4 | import java.util.concurrent.ScheduledExecutorService; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | public class ScheduledExecutorServiceDemo { 8 | public static void main(String[] args) { 9 | ScheduledExecutorService es = Executors.newScheduledThreadPool(10); 10 | es.scheduleAtFixedRate(new Runnable() { 11 | 12 | public void run() { 13 | try { 14 | Thread.sleep(1000); 15 | System.out.println(System.currentTimeMillis() / 1000); 16 | } catch (InterruptedException e) { 17 | e.printStackTrace(); 18 | } 19 | } 20 | }, 0, 2, TimeUnit.SECONDS); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ch2/AccountingSyncBad.java: -------------------------------------------------------------------------------- 1 | package ch2; 2 | 3 | public class AccountingSyncBad implements Runnable{ 4 | 5 | static int i = 0; 6 | 7 | // public synchronized void increase() { 8 | // i++; 9 | // } 10 | 11 | // 加上static相当于请求类的锁,所以没问题 12 | public synchronized static void increase() { 13 | i++; 14 | } 15 | 16 | public void run() { 17 | for (int j = 0; j < 10000000; j++) { 18 | increase(); 19 | } 20 | } 21 | 22 | public static void main(String[] args) throws InterruptedException { 23 | Thread t1 = new Thread(new AccountingSyncBad()); 24 | Thread t2 = new Thread(new AccountingSyncBad()); 25 | t1.start(); 26 | t2.start(); 27 | t1.join(); 28 | t2.join(); 29 | System.out.println(i); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/ch5/s5/s3/FutureMain.java: -------------------------------------------------------------------------------- 1 | package ch5.s5.s3; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | import java.util.concurrent.FutureTask; 7 | 8 | public class FutureMain { 9 | public static void main(String[] args) throws ExecutionException, InterruptedException { 10 | FutureTask future = new FutureTask(new RealData("a")); 11 | ExecutorService executor = Executors.newFixedThreadPool(1); 12 | executor.submit(future); 13 | 14 | System.out.println("请求完毕"); 15 | try { 16 | Thread.sleep(2000); 17 | } catch (InterruptedException e) { 18 | e.printStackTrace(); 19 | } 20 | System.out.println("数据 = " + future.get()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/ch6/s5/Example4.java: -------------------------------------------------------------------------------- 1 | package ch6.s5; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.ExecutionException; 5 | 6 | public class Example4 { 7 | public static Integer calc(Integer para){ 8 | return para / 0; 9 | } 10 | 11 | public static void main(String []args) throws ExecutionException, InterruptedException { 12 | CompletableFuture fu = CompletableFuture 13 | .supplyAsync(()->calc(50)) 14 | .exceptionally(ex -> { 15 | System.out.println(ex.toString()); 16 | return 0; 17 | }) 18 | .thenApply((i)->Integer.toString(i)) 19 | .thenApply((str)->"\""+str+"\"") 20 | .thenAccept(System.out::println); 21 | fu.get(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/ch7/s4/WatchActor.java: -------------------------------------------------------------------------------- 1 | package ch7.s4; 2 | 3 | import akka.actor.ActorRef; 4 | import akka.actor.Terminated; 5 | import akka.actor.UntypedActor; 6 | import akka.event.Logging; 7 | import akka.event.LoggingAdapter; 8 | 9 | public class WatchActor extends UntypedActor { 10 | private final LoggingAdapter log = Logging.getLogger(getContext().system(),this); 11 | 12 | public WatchActor(ActorRef ref) { 13 | getContext().watch(ref); 14 | } 15 | 16 | @Override 17 | public void onReceive(Object msg) throws Exception { 18 | if(msg instanceof Terminated){ 19 | System.out.println(String.format("%s has terminated, shutting down system", ((Terminated)msg).getActor().path())); 20 | getContext().system().shutdown(); 21 | }else{ 22 | unhandled(msg); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/FairLock.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | public class FairLock implements Runnable { 6 | public static ReentrantLock fairLock = new ReentrantLock(true); 7 | // public static ReentrantLock fairLock = new ReentrantLock(); 8 | 9 | public void run() { 10 | while (true){ 11 | try { 12 | fairLock.lock(); 13 | System.out.println(Thread.currentThread().getName()); 14 | }finally { 15 | fairLock.unlock(); 16 | } 17 | } 18 | } 19 | 20 | public static void main(String [] args){ 21 | FairLock r1 = new FairLock(); 22 | Thread t1 = new Thread(r1,"Thread_t1"); 23 | Thread t2 = new Thread(r1,"Thread_t2"); 24 | t1.start(); 25 | t2.start(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ch4/s4/AtomicIntegerDemo.java: -------------------------------------------------------------------------------- 1 | package ch4.s4; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | public class AtomicIntegerDemo { 6 | static AtomicInteger i = new AtomicInteger(); 7 | public static class AddThread implements Runnable{ 8 | 9 | public void run() { 10 | for(int k=0;k<10000;k++){ 11 | i.incrementAndGet(); 12 | } 13 | } 14 | } 15 | 16 | public static void main(String []args) throws InterruptedException { 17 | Thread []ts = new Thread[10]; 18 | for(int k=0;k<10;k++){ 19 | ts[k] = new Thread(new AddThread()); 20 | } 21 | for(int k=0;k<10;k++){ 22 | ts[k].start(); 23 | } 24 | for(int k=0;k<10;k++){ 25 | ts[k].join(); 26 | } 27 | System.out.println(i); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ch3/s2/ThreadPoolDemo.java: -------------------------------------------------------------------------------- 1 | package ch3.s2; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | public class ThreadPoolDemo { 7 | public static class MyTask implements Runnable { 8 | 9 | 10 | public void run() { 11 | System.out.println(System.currentTimeMillis() + " Thread id:" + Thread.currentThread().getId()); 12 | try { 13 | Thread.sleep(1000); 14 | } catch (InterruptedException e) { 15 | e.printStackTrace(); 16 | } 17 | } 18 | } 19 | 20 | // 前5个线程执行时间和后5个比差了1秒钟 21 | public static void main(String[] args) { 22 | MyTask task = new MyTask(); 23 | ExecutorService es = Executors.newFixedThreadPool(5); 24 | for (int i = 0; i < 10; i++) { 25 | es.submit(task); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/ch6/s7/LongAccumulatorDemo.java: -------------------------------------------------------------------------------- 1 | package ch6.s7; 2 | 3 | import org.omg.Messaging.SYNC_WITH_TRANSPORT; 4 | 5 | import java.util.Random; 6 | import java.util.concurrent.atomic.LongAccumulator; 7 | 8 | public class LongAccumulatorDemo { 9 | public static void main(String[] args) throws InterruptedException { 10 | LongAccumulator accumulator = new LongAccumulator(Long::max, Long.MIN_VALUE); 11 | Thread[] ts = new Thread[1000]; 12 | 13 | for(int i=0;i<1000;i++){ 14 | ts[i] = new Thread(()->{ 15 | Random random = new Random(); 16 | long value = random.nextLong(); 17 | accumulator.accumulate(value); 18 | }); 19 | ts[i].start(); 20 | } 21 | for(int i=0;i<1000;i++){ 22 | ts[i].join(); 23 | } 24 | System.out.println(accumulator.longValue()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ch2/ThreadGroupName.java: -------------------------------------------------------------------------------- 1 | package ch2; 2 | 3 | public class ThreadGroupName implements Runnable { 4 | 5 | public void run() { 6 | String groupAndName = Thread.currentThread().getThreadGroup().getName() + Thread.currentThread().getName(); 7 | while (true){ 8 | System.out.println(groupAndName); 9 | try { 10 | Thread.sleep(3000); 11 | } catch (InterruptedException e) { 12 | e.printStackTrace(); 13 | } 14 | } 15 | } 16 | 17 | public static void main(String[] args){ 18 | ThreadGroup tg = new ThreadGroup("PrintGroup"); 19 | Thread t1 = new Thread(tg, new ThreadGroupName(), "T1"); 20 | Thread t2 = new Thread(tg, new ThreadGroupName(), "T2"); 21 | t1.start(); 22 | t2.start(); 23 | System.out.println(tg.activeCount()); 24 | tg.list(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/SemapDemo.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | import java.util.concurrent.Semaphore; 6 | 7 | public class SemapDemo implements Runnable { 8 | //5个一组输出 9 | final Semaphore semp = new Semaphore(5); 10 | 11 | public void run() { 12 | try { 13 | semp.acquire(); 14 | Thread.sleep(2000); 15 | System.out.println(Thread.currentThread().getId() + " done!"); 16 | semp.release(); 17 | } catch (InterruptedException e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | 22 | public static void main(String []args){ 23 | ExecutorService exec = Executors.newFixedThreadPool(20); 24 | final SemapDemo demo = new SemapDemo(); 25 | for(int i=0;i<20;i++){ 26 | exec.submit(demo); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ch4/s4/AtomicIntegerArrayDemo.java: -------------------------------------------------------------------------------- 1 | package ch4.s4; 2 | 3 | import java.util.concurrent.atomic.AtomicIntegerArray; 4 | 5 | public class AtomicIntegerArrayDemo { 6 | static AtomicIntegerArray arr = new AtomicIntegerArray(10); 7 | 8 | public static class AddThread implements Runnable { 9 | 10 | public void run() { 11 | for (int k = 0; k < 10000; k++) 12 | arr.getAndIncrement(k % arr.length()); 13 | } 14 | } 15 | 16 | public static void main(String[] args) throws InterruptedException { 17 | Thread[] ts = new Thread[10]; 18 | for (int k = 0; k < 10; k++) { 19 | ts[k] = new Thread(new AddThread()); 20 | } 21 | for (int k = 0; k < 10; k++) { 22 | ts[k].start(); 23 | } 24 | for (int k = 0; k < 10; k++) { 25 | ts[k].join(); 26 | } 27 | System.out.println(arr); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/ReenterLock.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | public class ReenterLock implements Runnable { 6 | public static ReentrantLock lock = new ReentrantLock(); 7 | public static int i=0; 8 | 9 | public void run() { 10 | for(int j=0;j<10000000;j++){ 11 | lock.lock(); 12 | // lock.lock(); 13 | try { 14 | i++; 15 | }finally { 16 | lock.unlock(); 17 | // lock.unlock(); 18 | } 19 | } 20 | } 21 | 22 | public static void main(String[] args) throws InterruptedException { 23 | ReenterLock r1 = new ReenterLock(); 24 | Thread t1 = new Thread(r1); 25 | Thread t2 = new Thread(r1); 26 | t1.start(); 27 | t2.start(); 28 | t1.join(); 29 | t2.join(); 30 | System.out.println(i); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/ch6/s6/Point.java: -------------------------------------------------------------------------------- 1 | package ch6.s6; 2 | 3 | import java.util.concurrent.locks.StampedLock; 4 | 5 | public class Point { 6 | private double x,y; 7 | private final StampedLock s1 = new StampedLock(); 8 | 9 | void move(double deltaX, double deltaY){ 10 | long stamp = s1.writeLock(); 11 | try{ 12 | x += deltaX; 13 | y += deltaY; 14 | } finally { 15 | s1.unlockWrite(stamp); 16 | } 17 | } 18 | 19 | double distanceFromOrigin(){ 20 | long stamp = s1.tryOptimisticRead(); 21 | double currentX = x, currentY = y; 22 | if(!s1.validate(stamp)){ 23 | stamp = s1.readLock(); 24 | try{ 25 | currentX = x; 26 | currentY = y; 27 | } finally { 28 | s1.unlockRead(stamp); 29 | } 30 | } 31 | return Math.sqrt(currentX*currentX + currentY*currentY); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/TimeLock.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | import java.util.concurrent.locks.ReentrantLock; 5 | 6 | public class TimeLock implements Runnable { 7 | public static ReentrantLock lock = new ReentrantLock(); 8 | 9 | public void run() { 10 | try { 11 | if (lock.tryLock(5, TimeUnit.SECONDS)) { 12 | Thread.sleep(6000); 13 | } else { 14 | System.out.println("Get lock failed"); 15 | } 16 | } catch (InterruptedException e) { 17 | e.printStackTrace(); 18 | } finally { 19 | if(lock.isHeldByCurrentThread()) 20 | lock.unlock(); 21 | } 22 | } 23 | 24 | public static void main(String [] args){ 25 | TimeLock lock1 = new TimeLock(); 26 | Thread t1 = new Thread(lock1); 27 | Thread t2 = new Thread(lock1); 28 | t1.start(); 29 | t2.start(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ch6/s2/ConstrMethodRef.java: -------------------------------------------------------------------------------- 1 | package ch6.s2; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class ConstrMethodRef { 7 | 8 | public static class User { 9 | private int id; 10 | private String name; 11 | 12 | public User(int id, String name) { 13 | this.id = id; 14 | this.name = name; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | } 21 | 22 | @FunctionalInterface 23 | interface UserFactory { 24 | U create(int id, String name); 25 | } 26 | 27 | static UserFactory uf = User::new; 28 | 29 | public static void main(String[] args) { 30 | List users = new ArrayList(); 31 | for(int i=0;i<10;i++){ 32 | users.add(uf.create(i,"billy"+Integer.toString(i))); 33 | } 34 | users.stream().map(User::getName).forEach(System.out::println); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/LockSupportDemo.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.concurrent.locks.LockSupport; 4 | 5 | public class LockSupportDemo { 6 | 7 | public static Object u = new Object(); 8 | static ChangeObjectThread t1 = new ChangeObjectThread("t1"); 9 | static ChangeObjectThread t2 = new ChangeObjectThread("t2"); 10 | 11 | public static class ChangeObjectThread extends Thread { 12 | public ChangeObjectThread(String name) { 13 | super.setName(name); 14 | } 15 | 16 | 17 | public void run() { 18 | synchronized (u) { 19 | System.out.println("in " + getName()); 20 | LockSupport.park(); 21 | } 22 | } 23 | } 24 | 25 | public static void main(String[] args) throws InterruptedException { 26 | t1.start(); 27 | Thread.sleep(100); 28 | t2.start(); 29 | LockSupport.unpark(t1); 30 | LockSupport.unpark(t2); 31 | t1.join(); 32 | t2.join(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/ReenterLockCondition.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.concurrent.locks.Condition; 4 | import java.util.concurrent.locks.ReentrantLock; 5 | 6 | public class ReenterLockCondition implements Runnable { 7 | public static ReentrantLock lock = new ReentrantLock(); 8 | public static Condition condition = lock.newCondition(); 9 | 10 | public void run() { 11 | try{ 12 | lock.lock(); 13 | condition.await(); 14 | System.out.println("Thread is going on"); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | }finally { 18 | lock.unlock(); 19 | } 20 | } 21 | 22 | public static void main(String [] args) throws InterruptedException { 23 | ReenterLockCondition r1 = new ReenterLockCondition(); 24 | Thread t1= new Thread(r1); 25 | t1.start(); 26 | Thread.sleep(2000); 27 | lock.lock(); 28 | condition.signal(); 29 | lock.unlock(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ch2/BadSuspend.java: -------------------------------------------------------------------------------- 1 | package ch2; 2 | 3 | public class BadSuspend { 4 | public static Object u = new Object(); 5 | static ChangeObjectThread t1 = new ChangeObjectThread("t1"); 6 | static ChangeObjectThread t2 = new ChangeObjectThread("t2"); 7 | 8 | public static class ChangeObjectThread extends Thread{ 9 | public ChangeObjectThread(String name) { 10 | super.setName(name); 11 | } 12 | 13 | 14 | public void run() { 15 | synchronized (u){ 16 | System.out.println("in "+ getName()); 17 | Thread.currentThread().suspend(); 18 | } 19 | } 20 | 21 | } 22 | 23 | // 导致resume不生效的执行顺序可能是这样的: 24 | // 打印t1 => t1在suspend => t2等待u释放 => t1被resume => t2被resume => u释放打印t2 => t2被suspend => 永远无法结束 25 | public static void main(String []args) throws InterruptedException { 26 | t1.start(); 27 | Thread.sleep(100); 28 | t2.start(); 29 | t1.resume(); 30 | t2.resume(); 31 | t1.join(); 32 | t2.join(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/CountDownLatchDemo.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.CountDownLatch; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | public class CountDownLatchDemo implements Runnable { 9 | static final CountDownLatch end = new CountDownLatch(10); 10 | static final CountDownLatchDemo demo = new CountDownLatchDemo(); 11 | 12 | 13 | public void run() { 14 | try { 15 | Thread.sleep(new Random().nextInt(10) * 1000); 16 | System.out.println("check complete!"); 17 | end.countDown(); 18 | } catch (InterruptedException e) { 19 | e.printStackTrace(); 20 | } 21 | } 22 | 23 | public static void main(String[] args) throws InterruptedException { 24 | ExecutorService exec = Executors.newFixedThreadPool(10); 25 | for (int i = 0; i < 10; i++) { 26 | exec.submit(demo); 27 | } 28 | end.await(); 29 | System.out.println("Fire!"); 30 | exec.shutdown(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 guanpengchn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/ch6/s5/Example1.java: -------------------------------------------------------------------------------- 1 | package ch6.s5; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.ExecutionException; 5 | 6 | public class Example1 { 7 | public static class AskThread implements Runnable{ 8 | CompletableFuture re=null; 9 | 10 | public AskThread(CompletableFuture re) { 11 | this.re = re; 12 | } 13 | 14 | @Override 15 | public void run() { 16 | int myRe = 0; 17 | try{ 18 | myRe = re.get() * re.get(); // 这里会阻塞 19 | } catch (InterruptedException e) { 20 | e.printStackTrace(); 21 | } catch (ExecutionException e) { 22 | e.printStackTrace(); 23 | } 24 | System.out.println(myRe); 25 | } 26 | } 27 | 28 | public static void main(String []args) throws InterruptedException { 29 | final CompletableFuture future = new CompletableFuture<>(); 30 | new Thread(new AskThread(future)).start(); 31 | Thread.sleep(1000); 32 | future.complete(60); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/LockSupportIntDemo.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.concurrent.locks.LockSupport; 4 | 5 | public class LockSupportIntDemo { 6 | 7 | public static Object u = new Object(); 8 | static ChangeObjectThread t1 = new ChangeObjectThread("t1"); 9 | static ChangeObjectThread t2 = new ChangeObjectThread("t2"); 10 | 11 | public static class ChangeObjectThread extends Thread { 12 | public ChangeObjectThread(String name) { 13 | super.setName(name); 14 | } 15 | 16 | 17 | public void run() { 18 | synchronized (u) { 19 | System.out.println("in " + getName()); 20 | LockSupport.park(); 21 | if (Thread.interrupted()) { 22 | System.out.println(getName() + "被中断了"); 23 | } 24 | } 25 | System.out.println(getName() + "执行结束"); 26 | } 27 | } 28 | 29 | public static void main(String[] args) throws InterruptedException { 30 | t1.start(); 31 | Thread.sleep(100); 32 | t2.start(); 33 | t1.interrupt(); 34 | LockSupport.unpark(t2); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/ch5/s3/Consumer.java: -------------------------------------------------------------------------------- 1 | package ch5.s3; 2 | 3 | import java.text.MessageFormat; 4 | import java.util.Random; 5 | import java.util.concurrent.BlockingQueue; 6 | 7 | public class Consumer implements Runnable { 8 | private BlockingQueue queue; 9 | private static final int SLEEPTIME = 1000; 10 | 11 | public Consumer(BlockingQueue queue) { 12 | this.queue = queue; 13 | } 14 | 15 | 16 | public void run() { 17 | System.out.println("start Consumer id=" + Thread.currentThread().getId()); 18 | Random r = new Random(); 19 | 20 | try { 21 | while (true) { 22 | PCData data = queue.take(); 23 | if (null != data) { 24 | int re = data.getData() * data.getData(); 25 | System.out.println(MessageFormat.format("{0}*{1}={2}", data.getData(), data.getData(), re)); 26 | Thread.sleep(r.nextInt(SLEEPTIME)); 27 | } 28 | } 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | Thread.currentThread().interrupt(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/ch4/s3/ThreadLocalDemo.java: -------------------------------------------------------------------------------- 1 | package ch4.s3; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | 9 | public class ThreadLocalDemo { 10 | private static ThreadLocal t1 = new ThreadLocal(); 11 | public static class ParseDate implements Runnable{ 12 | int i=0; 13 | public ParseDate(int i){this.i=i;} 14 | 15 | public void run() { 16 | try{ 17 | if(t1.get()==null){ 18 | t1.set(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); 19 | } 20 | Date t =t1.get().parse("2015-03-29 19:29:"+i%60); 21 | System.out.println(i+":"+t); 22 | } catch (ParseException e) { 23 | e.printStackTrace(); 24 | } 25 | } 26 | } 27 | public static void main(String []args){ 28 | ExecutorService es = Executors.newFixedThreadPool(10); 29 | for(int i=0;i<1000;i++){ 30 | es.execute(new ParseDate(i)); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/ch1/MultiThreadLong.java: -------------------------------------------------------------------------------- 1 | package ch1; 2 | 3 | public class MultiThreadLong { 4 | public static long t = 0; 5 | 6 | public static class ChangeT implements Runnable { 7 | private long to; 8 | 9 | public ChangeT(long to) { 10 | this.to = to; 11 | } 12 | 13 | public void run() { 14 | while (true) { 15 | MultiThreadLong.t = to; 16 | Thread.yield(); 17 | } 18 | } 19 | } 20 | 21 | public static class ReadT implements Runnable { 22 | public void run() { 23 | while (true) { 24 | long tmp = MultiThreadLong.t; 25 | if (tmp != 111L && tmp != -999L && tmp != 333L && tmp != -444L) 26 | System.out.println(tmp); 27 | Thread.yield(); 28 | } 29 | } 30 | } 31 | 32 | public static void main(String[] args) { 33 | new Thread(new ChangeT(111L)).start(); 34 | new Thread(new ChangeT(-999L)).start(); 35 | new Thread(new ChangeT(333L)).start(); 36 | new Thread(new ChangeT(-444L)).start(); 37 | new Thread(new ReadT()).start(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/ch7/s4/MyWorker.java: -------------------------------------------------------------------------------- 1 | package ch7.s4; 2 | 3 | import akka.actor.UntypedActor; 4 | import akka.event.Logging; 5 | import akka.event.LoggingAdapter; 6 | 7 | public class MyWorker extends UntypedActor { 8 | private final LoggingAdapter log = Logging.getLogger(getContext().system(), this); 9 | public static enum Msg{ 10 | WORKING, DONE, CLOSE; 11 | } 12 | 13 | @Override 14 | public void preStart() throws Exception { 15 | System.out.println("MyWorker is starting"); 16 | } 17 | 18 | @Override 19 | public void postStop() throws Exception { 20 | System.out.println("MyWorker is stopping"); 21 | 22 | } 23 | 24 | @Override 25 | public void onReceive(Object msg) throws Exception { 26 | if(msg == Msg.WORKING){ 27 | System.out.println("I am working"); 28 | } 29 | if(msg == Msg.DONE){ 30 | System.out.println("Stop working"); 31 | } 32 | if(msg == Msg.CLOSE){ 33 | System.out.println("I will shutdown"); 34 | getSender().tell(Msg.CLOSE,getSelf()); 35 | getContext().stop(getSelf()); 36 | }else{ 37 | unhandled(msg); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/ch2/AccountingVol.java: -------------------------------------------------------------------------------- 1 | package ch2; 2 | 3 | public class AccountingVol implements Runnable { 4 | static AccountingVol instance = new AccountingVol(); 5 | static volatile int i = 0; 6 | 7 | // public static void increase() { 8 | // i++; 9 | // } 10 | // 11 | // 12 | // public void run() { 13 | // for (int j = 0; j < 10000000; j++) { 14 | // increase(); 15 | // } 16 | // } 17 | 18 | // 19 | // public void run() { 20 | // for (int j = 0; j < 10000000; j++) { 21 | // synchronized (instance){ 22 | // i++; 23 | // } 24 | // } 25 | // } 26 | 27 | public synchronized static void increase() { 28 | i++; 29 | } 30 | 31 | public void run() { 32 | for (int j = 0; j < 10000000; j++) { 33 | increase(); 34 | } 35 | } 36 | 37 | // synchronized锁的是对象,不是函数 38 | public static void main(String[] args) throws InterruptedException { 39 | Thread t1 = new Thread(instance); 40 | Thread t2 = new Thread(instance); 41 | t1.start(); 42 | t2.start(); 43 | t1.join(); 44 | t2.join(); 45 | System.out.println(i); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /notes/ch1.md: -------------------------------------------------------------------------------- 1 | ## 第1章 走入并行世界 1 2 | 3 | > Give it up. The whole "parallel computing is the future" is a bunch of crock. 4 | 5 | ### 1.1 何去何从的并行计算 1 6 | 7 | #### 1.1.1 忘掉那该死的并行 2 8 | 9 | - BitKeeper真惨 10 | - Git真好用 11 | - 并行计算只有在图像处理和服务器编程2个领域可以使用 12 | 13 | #### 1.1.2 可怕的现实:摩尔定律的失效 4 14 | 15 | - CPU遇到了不可逾越的瓶颈 16 | 17 | #### 1.1.3 柳暗花明:不断地前进 5 18 | 19 | - CPU核心在不断变多 20 | 21 | #### 1.1.4 光明或是黑暗 6 22 | 23 | ### 1.2 你必须知道的几个概念 6 24 | 25 | #### 1.2.1 同步(Synchronous)和异步(Asynchronous) 7 26 | 27 | - 见书中图 28 | 29 | #### 1.2.2 并发(Concurrency)和并行(Parallelism) 8 30 | 31 | - 见书中图 32 | 33 | #### 1.2.3 临界区 9 34 | #### 1.2.4 阻塞(Blocking)和非阻塞(Non-Blocking) 9 35 | #### 1.2.5 死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock) 9 36 | 37 | ### 1.3 并发级别 11 38 | 39 | #### 1.3.1 阻塞(Blocking) 11 40 | #### 1.3.2 无饥饿(Starvation-Free) 11 41 | #### 1.3.3 无障碍(Obstruction-Free) 12 42 | #### 1.3.4 无锁(Lock-Free) 12 43 | #### 1.3.5 无等待(Wait-Free) 13 44 | 45 | ### 1.4 有关并行的两个重要定律 13 46 | 47 | #### 1.4.1 Amdahl定律 13 48 | #### 1.4.2 Gustafson定律 16 49 | #### 1.4.3 Amdahl定律和Gustafson定律是否相互矛盾 16 50 | 51 | ### 1.5 回到Java:JMM 17 52 | 53 | #### 1.5.1 原子性(Atomicity) 18 54 | #### 1.5.2 可见性(Visibility) 20 55 | #### 1.5.3 有序性(Ordering) 22 56 | #### 1.5.4 哪些指令不能重排:Happen-Before规则 27 57 | 58 | ### 1.6 参考文献 27 -------------------------------------------------------------------------------- /src/main/java/ch5/s3/Main.java: -------------------------------------------------------------------------------- 1 | package ch5.s3; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | import java.util.concurrent.LinkedBlockingDeque; 7 | 8 | public class Main { 9 | public static void main(String[]args) throws InterruptedException { 10 | BlockingQueue queue = new LinkedBlockingDeque(10); 11 | Producer producer1 = new Producer(queue); 12 | Producer producer2 = new Producer(queue); 13 | Producer producer3 = new Producer(queue); 14 | Consumer consumer1 = new Consumer(queue); 15 | Consumer consumer2 = new Consumer(queue); 16 | Consumer consumer3 = new Consumer(queue); 17 | ExecutorService service = Executors.newCachedThreadPool(); 18 | service.execute(producer1); 19 | service.execute(producer2); 20 | service.execute(producer3); 21 | service.execute(consumer1); 22 | service.execute(consumer2); 23 | service.execute(consumer3); 24 | Thread.sleep(10*1000); 25 | producer1.stop(); 26 | producer2.stop(); 27 | producer3.stop(); 28 | Thread.sleep(3000); 29 | service.shutdown(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/ch3/s2/RejectThreadPoolDemo.java: -------------------------------------------------------------------------------- 1 | package ch3.s2; 2 | 3 | import java.util.concurrent.*; 4 | 5 | public class RejectThreadPoolDemo { 6 | public static class MyTask implements Runnable { 7 | 8 | public void run() { 9 | System.out.println(System.currentTimeMillis() + "thread id:" + Thread.currentThread().getId()); 10 | try { 11 | Thread.sleep(100); 12 | } catch (InterruptedException e) { 13 | e.printStackTrace(); 14 | } 15 | } 16 | } 17 | 18 | public static void main(String[] args) throws InterruptedException { 19 | MyTask task = new MyTask(); 20 | ExecutorService es = new ThreadPoolExecutor(5, 5, 21 | 0L, TimeUnit.MILLISECONDS, 22 | new LinkedBlockingDeque(10), 23 | Executors.defaultThreadFactory(), 24 | new RejectedExecutionHandler() { 25 | 26 | public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { 27 | System.out.println(r.toString() + " is discard"); 28 | } 29 | }); 30 | for(int i=0;i(), 24 | new ThreadFactory() { 25 | 26 | public Thread newThread(Runnable r) { 27 | Thread t = new Thread(r); 28 | t.setDaemon(true); 29 | System.out.println("create " + t); 30 | return t; 31 | } 32 | }); 33 | for (int i = 0; i < 5; i++) { 34 | es.submit(task); 35 | } 36 | Thread.sleep(2000); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | java.concurrent.programming 8 | java.concurrent.programming 9 | 1.0 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-compiler-plugin 15 | 16 | 8 17 | 8 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | com.lmax 26 | disruptor 27 | 3.3.2 28 | 29 | 30 | com.typesafe.akka 31 | akka-actor_2.11 32 | 2.3.7 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/java/ch2/PriorityDemo.java: -------------------------------------------------------------------------------- 1 | package ch2; 2 | 3 | public class PriorityDemo { 4 | public static class HighPriority extends Thread{ 5 | static int count = 0; 6 | 7 | public void run() { 8 | while (true){ 9 | synchronized (PriorityDemo.class){ 10 | count ++ ; 11 | if(count > 10000000){ 12 | System.out.println("HighPriority finished"); 13 | break; 14 | } 15 | } 16 | } 17 | } 18 | } 19 | 20 | public static class LowPriority extends Thread{ 21 | static int count = 0; 22 | 23 | public void run() { 24 | while (true){ 25 | synchronized (PriorityDemo.class){ 26 | count ++ ; 27 | if(count > 10000000){ 28 | System.out.println("LowPriority finished"); 29 | break; 30 | } 31 | } 32 | } 33 | } 34 | } 35 | 36 | public static void main(String []args){ 37 | Thread high = new HighPriority(); 38 | Thread low = new LowPriority(); 39 | high.setPriority(Thread.MAX_PRIORITY); 40 | low.setPriority(Thread.MIN_PRIORITY); 41 | high.start(); 42 | low.start(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/ch4/s4/AtomicIntegerFieldUpdaterDemo.java: -------------------------------------------------------------------------------- 1 | package ch4.s4; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; 5 | 6 | public class AtomicIntegerFieldUpdaterDemo { 7 | public static class Candidate { 8 | int id; 9 | volatile int score; 10 | } 11 | 12 | public final static AtomicIntegerFieldUpdater scoreUpdater = 13 | AtomicIntegerFieldUpdater.newUpdater(Candidate.class, "score"); 14 | public static AtomicInteger allscore = new AtomicInteger(0); 15 | 16 | public static void main(String[] args) throws InterruptedException { 17 | final Candidate stu = new Candidate(); 18 | Thread[] t = new Thread[10000]; 19 | for (int i = 0; i < 10000; i++) { 20 | t[i] = new Thread() { 21 | 22 | public void run() { 23 | if (Math.random() > 0.4) { 24 | scoreUpdater.incrementAndGet(stu); 25 | allscore.incrementAndGet(); 26 | } 27 | } 28 | }; 29 | t[i].start(); 30 | } 31 | for (int i = 0; i < 10000; i++) { 32 | t[i].join(); 33 | } 34 | System.out.println("score=" + stu.score); 35 | System.out.println("allscore=" + allscore); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /notes/ch7.md: -------------------------------------------------------------------------------- 1 | ## 第7章 使用Akka构建高并发程序 289 2 | 3 | - Akka提供了一种称为Actor的并发模型,粒度比线程更小 4 | - 其次Akka中提供了一套容错机制,允许在Actor出现异常时进行一些恢复或者重置操作 5 | - Akka不仅可以在单机上构建高并发程序,也可以在网络中构件分布式程序 6 | 7 | ### 7.1 新并发模型:Actor 290 8 | 9 | - 完全忘记线程,使用Actor 10 | 11 | ### 7.2 Akka之Hello World 290 12 | 13 | - [代码](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch7/s2) 14 | - 多个不同的Actor有可能会被同一个县城执行,一个Actor也有可能被不同县城执行 15 | - 不要在一个Actor中执行耗时的代码 16 | 17 | ### 7.3 有关消息投递的一些说明 293 18 | 19 | - 消息满足不可变性 20 | - [ImmutableMessage](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch7/s3/ImmutableMessage.java) 21 | - 消息投递3种策略: 22 | - 至多一次投递,每条消息最多会被投递一次,偶尔丢失消息 23 | - 至少一次投递,每条消息至少会被投递一次,直到成功为止,会收到重复消息但不会丢失消息 24 | - 精确的消息投递,所有消息保证被精确地投递并成功接收一次,既不丢失,也不重复 25 | - Akka一定程度保证顺序性,消息投递不具备可传递性 26 | 27 | ### 7.4 Actor的生命周期 295 28 | 29 | - [代码](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch7/s4) 30 | 31 | ### 7.5 监督策略 298 32 | 33 | - OneForOneStrategy,默认策略 34 | - AllForOneStrategy 35 | 36 | ### 7.6 选择Actor 303 37 | ### 7.7 消息收件箱(Inbox) 303 38 | ### 7.8 消息路由 305 39 | ### 7.9 Actor的内置状态转换 308 40 | ### 7.10 询问模式:Actor中的Future 311 41 | ### 7.11 多个Actor同时修改数据:Agent 313 42 | ### 7.12 像数据库一样操作内存数据:软件事务内存 316 43 | ### 7.13 一个有趣的例子:并发粒子群的实现 319 44 | 45 | #### 7.13.1 什么是粒子群算法 320 46 | #### 7.13.2 粒子群算法的计算过程 320 47 | #### 7.13.3 粒子群算法能做什么 322 48 | #### 7.13.4 使用Akka实现粒子群 323 49 | 50 | ### 7.14 参考文献 330 -------------------------------------------------------------------------------- /src/main/java/ch5/s3/Producer.java: -------------------------------------------------------------------------------- 1 | package ch5.s3; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.BlockingQueue; 5 | import java.util.concurrent.TimeUnit; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | public class Producer implements Runnable { 9 | private volatile boolean isRunning = true; 10 | private BlockingQueue queue; 11 | private static AtomicInteger count = new AtomicInteger(); 12 | private static final int SLEEPTIME = 1000; 13 | 14 | public Producer(BlockingQueue queue) { 15 | this.queue = queue; 16 | } 17 | 18 | 19 | public void run() { 20 | PCData data = null; 21 | Random r = new Random(); 22 | 23 | System.out.println("start producer id=" + Thread.currentThread().getId()); 24 | try { 25 | while (isRunning) { 26 | Thread.sleep(r.nextInt(SLEEPTIME)); 27 | data = new PCData(count.incrementAndGet()); 28 | System.out.println(data + " is put into queue"); 29 | if (!queue.offer(data, 2, TimeUnit.SECONDS)) { 30 | System.err.println("failed to put data: " + data); 31 | } 32 | } 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | Thread.currentThread().interrupt(); 36 | } 37 | } 38 | 39 | public void stop() { 40 | isRunning = false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/ch2/SimpleWN.java: -------------------------------------------------------------------------------- 1 | package ch2; 2 | 3 | public class SimpleWN { 4 | final static Object object = new Object(); 5 | 6 | public static class T1 extends Thread { 7 | 8 | 9 | public void run() { 10 | synchronized (object) { 11 | System.out.println(System.currentTimeMillis() + "T1"); 12 | try { 13 | System.out.println(System.currentTimeMillis() + "T1 wait for object"); 14 | object.wait(); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | System.out.println(System.currentTimeMillis() + "T1 end"); 19 | } 20 | } 21 | } 22 | 23 | public static class T2 extends Thread { 24 | 25 | 26 | public void run() { 27 | synchronized (object) { 28 | System.out.println(System.currentTimeMillis() + "T2"); 29 | object.notify(); 30 | System.out.println(System.currentTimeMillis() + "T2 end"); 31 | try { 32 | Thread.sleep(2000); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | } 38 | } 39 | 40 | public static void main(String[] args) { 41 | Thread t1 = new T1(); 42 | Thread t2 = new T2(); 43 | t1.start(); 44 | t2.start(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/IntLock.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | public class IntLock implements Runnable { 6 | public static ReentrantLock lock1 = new ReentrantLock(); 7 | public static ReentrantLock lock2 = new ReentrantLock(); 8 | int lock; 9 | 10 | public IntLock(int lock) { 11 | this.lock = lock; 12 | } 13 | 14 | 15 | public void run() { 16 | try { 17 | if (this.lock == 1) { 18 | lock1.lockInterruptibly(); 19 | Thread.sleep(500); 20 | lock2.lockInterruptibly(); 21 | } else { 22 | lock2.lockInterruptibly(); 23 | Thread.sleep(500); 24 | lock1.lockInterruptibly(); 25 | } 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } finally { 29 | if (lock1.isHeldByCurrentThread()) 30 | lock1.unlock(); 31 | if (lock2.isHeldByCurrentThread()) 32 | lock2.unlock(); 33 | System.out.println(this.lock + "线程退出"); 34 | } 35 | } 36 | 37 | public static void main(String[] args) throws InterruptedException { 38 | IntLock r1 = new IntLock(1); 39 | IntLock r2 = new IntLock(2); 40 | Thread t1 = new Thread(r1); 41 | Thread t2 = new Thread(r2); 42 | t1.start(); 43 | t2.start(); 44 | Thread.sleep(1000); 45 | t2.interrupt(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/ch4/s3/WeakVsHashMap.java: -------------------------------------------------------------------------------- 1 | package ch4.s3; 2 | 3 | import java.util.HashMap; 4 | import java.util.Iterator; 5 | import java.util.Map; 6 | import java.util.WeakHashMap; 7 | 8 | /** 9 | * WeakHashMap,此种Map的特点是,当除了自身有对key的引用外,此key没有其他引用那么此map会自动丢弃此值, 10 | * 见实例:此例子中声明了两个Map对象,一个是HashMap,一个是WeakHashMap,同时向两个map中放入a、b两个对象, 11 | * 当HashMap remove掉a 并且将a、b都指向null时,WeakHashMap中的a将自动被回收掉。出现这个状况的原因是, 12 | * 对于a对象而言,当HashMap remove掉并且将a指向null后,除了WeakHashMap中还保存a外已经没有指向a的指针了, 13 | * 所以WeakHashMap会自动舍弃掉a,而对于b对象虽然指向了null,但HashMap中还有指向b的指针,所以WeakHashMap将会保留 14 | */ 15 | public class WeakVsHashMap { 16 | 17 | public static void main(String[] args) throws Exception { 18 | String a = new String("a"); 19 | String b = new String("b"); 20 | Map weakmap = new WeakHashMap(); 21 | Map map = new HashMap(); 22 | map.put(a, "aaa"); 23 | map.put(b, "bbb"); 24 | 25 | 26 | weakmap.put(a, "aaa"); 27 | weakmap.put(b, "bbb"); 28 | 29 | map.remove(a); 30 | 31 | a = null; 32 | b = null; 33 | 34 | System.gc(); 35 | Iterator i = map.entrySet().iterator(); 36 | while (i.hasNext()) { 37 | Map.Entry en = (Map.Entry) i.next(); 38 | System.out.println("map:" + en.getKey() + ":" + en.getValue()); 39 | } 40 | 41 | Iterator j = weakmap.entrySet().iterator(); 42 | while (j.hasNext()) { 43 | Map.Entry en = (Map.Entry) j.next(); 44 | System.out.println("weakmap:" + en.getKey() + ":" + en.getValue()); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/ch3/s2/ExtThreadPool.java: -------------------------------------------------------------------------------- 1 | package ch3.s2; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.LinkedBlockingDeque; 5 | import java.util.concurrent.ThreadPoolExecutor; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | public class ExtThreadPool { 9 | public static class MyTask implements Runnable { 10 | public String name; 11 | 12 | public MyTask(String name) { 13 | this.name = name; 14 | } 15 | 16 | 17 | public void run() { 18 | System.out.println("正在执行" + ":Thread id" + Thread.currentThread().getId() + ", Task name:" + this.name); 19 | } 20 | } 21 | 22 | public static void main(String[] args) throws InterruptedException { 23 | ExecutorService es = new ThreadPoolExecutor(5, 5, 0L, 24 | TimeUnit.MILLISECONDS, 25 | new LinkedBlockingDeque()) { 26 | 27 | protected void beforeExecute(Thread t, Runnable r) { 28 | System.out.println("准备执行:" + ((MyTask) r).name); 29 | } 30 | 31 | 32 | protected void afterExecute(Runnable r, Throwable t) { 33 | System.out.println("执行完成:" + ((MyTask) r).name); 34 | } 35 | 36 | 37 | protected void terminated() { 38 | System.out.println("线程池退出!"); 39 | } 40 | }; 41 | for(int i =0;i<5;i++){ 42 | MyTask task = new MyTask("TASK-GEYM-"+i); 43 | es.execute(task); 44 | Thread.sleep(10); 45 | } 46 | es.shutdown(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/ch4/s5/DeadLock.java: -------------------------------------------------------------------------------- 1 | package ch4.s5; 2 | 3 | public class DeadLock extends Thread { 4 | protected Object tool; 5 | static Object fork1 = new Object(); 6 | static Object fork2 = new Object(); 7 | 8 | public DeadLock(Object obj){ 9 | this.tool = obj; 10 | if(tool == fork1){ 11 | this.setName("哲学家A"); 12 | } 13 | if(tool == fork2){ 14 | this.setName("哲学家B"); 15 | } 16 | } 17 | 18 | 19 | public void run() { 20 | if(tool == fork1){ 21 | synchronized (fork1){ 22 | try { 23 | Thread.sleep(500); 24 | } catch (InterruptedException e) { 25 | e.printStackTrace(); 26 | } 27 | synchronized (fork2){ 28 | System.out.println("哲学家A开始吃饭了"); 29 | } 30 | } 31 | } 32 | if(tool == fork2){ 33 | synchronized (fork2){ 34 | try { 35 | Thread.sleep(500); 36 | } catch (InterruptedException e) { 37 | e.printStackTrace(); 38 | } 39 | synchronized (fork1){ 40 | System.out.println("哲学家B开始吃饭了"); 41 | } 42 | } 43 | } 44 | } 45 | 46 | public static void main(String []args) throws InterruptedException { 47 | DeadLock 哲学家A = new DeadLock(fork1); 48 | DeadLock 哲学家B = new DeadLock(fork2); 49 | 哲学家A.start(); 50 | 哲学家B.start(); 51 | Thread.sleep(1000); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/ch5/s4/FalseSharing.java: -------------------------------------------------------------------------------- 1 | package ch5.s4; 2 | 3 | public class FalseSharing implements Runnable { 4 | public final static int NUM_THREADS = 2; 5 | public final static long ITERATIONS = 500L * 1000L * 1000L; 6 | private final int arrayIndex; 7 | 8 | private static VolatileLong[] longs = new VolatileLong[NUM_THREADS]; 9 | static { 10 | for(int i=0;i workQueue) { 8 | super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); 9 | } 10 | 11 | 12 | public void execute(Runnable task) { 13 | super.execute(wrap(task, clientTrace(), Thread.currentThread().getName())); 14 | } 15 | 16 | 17 | public Future submit(Runnable task) { 18 | return super.submit(wrap(task, clientTrace(), Thread.currentThread().getName())); 19 | } 20 | 21 | public Exception clientTrace() { 22 | return new Exception("Client stack trace"); 23 | } 24 | 25 | public Runnable wrap(final Runnable task, final Exception clientStack, String clientThreadName) { 26 | return new Runnable() { 27 | 28 | public void run() { 29 | try { 30 | task.run(); 31 | } catch (Exception e) { 32 | clientStack.printStackTrace(); 33 | throw e; 34 | } 35 | } 36 | }; 37 | } 38 | 39 | public static class DivTask implements Runnable { 40 | int a, b; 41 | 42 | public DivTask(int a, int b) { 43 | this.a = a; 44 | this.b = b; 45 | } 46 | 47 | 48 | public void run() { 49 | double re = a / b; 50 | System.out.println(re); 51 | } 52 | } 53 | 54 | public static void main(String[] args) { 55 | ThreadPoolExecutor pools = new TraceThreadPoolExecutor(0, Integer.MAX_VALUE, 0L, TimeUnit.SECONDS, new 56 | SynchronousQueue()); 57 | for (int i = 0; i < 5; i++) { 58 | pools.execute(new DivTask(100, i)); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/ch5/s7/Main.java: -------------------------------------------------------------------------------- 1 | package ch5.s7; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.*; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | public class Main { 9 | static int[] arr; 10 | static ExecutorService pool = Executors.newCachedThreadPool(); 11 | static final int Thread_Num=2; 12 | static AtomicInteger result=new AtomicInteger(-1); 13 | 14 | public static int search(int searchValue, int beginPos,int endPos){ 15 | int i=0; 16 | for(i=beginPos;i=0){ 18 | return result.get(); 19 | } 20 | if(arr[i] == searchValue){ 21 | if(!result.compareAndSet(-1,i)){ 22 | return result.get(); 23 | } 24 | return i; 25 | } 26 | } 27 | return -1; 28 | } 29 | 30 | public static int pSearch(int searchValue) throws ExecutionException, InterruptedException { 31 | int subArrSize = arr.length/Thread_Num+1; 32 | List> re = new ArrayList>(); 33 | for(int i=0;i=arr.length)end=arr.length; 36 | re.add(pool.submit(new SearchTask(searchValue,i,end))); 37 | } 38 | for(Future fu:re){ 39 | if(fu.get()>=0) 40 | return fu.get(); 41 | } 42 | return -1; 43 | } 44 | 45 | public static class SearchTask implements Callable { 46 | int begin,end,searchValue; 47 | 48 | public SearchTask(int begin, int end, int searchValue) { 49 | this.begin = begin; 50 | this.end = end; 51 | this.searchValue = searchValue; 52 | } 53 | 54 | @Override 55 | public Integer call() throws Exception { 56 | int re = search(searchValue,begin,end); 57 | return re; 58 | } 59 | 60 | 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/ch3/s2/CountTask.java: -------------------------------------------------------------------------------- 1 | package ch3.s2; 2 | 3 | import java.util.ArrayList; 4 | import java.util.concurrent.ExecutionException; 5 | import java.util.concurrent.ForkJoinPool; 6 | import java.util.concurrent.ForkJoinTask; 7 | import java.util.concurrent.RecursiveTask; 8 | 9 | public class CountTask extends RecursiveTask { 10 | private static final int THRESHOLD = 10000; 11 | private long start; 12 | private long end; 13 | 14 | public CountTask(long start, long end) { 15 | this.start = start; 16 | this.end = end; 17 | } 18 | 19 | 20 | protected Long compute() { 21 | long sum = 0; 22 | boolean canCompute = (end - start) < THRESHOLD; 23 | if (canCompute) { 24 | for (long i = start; i <= end; i++) { 25 | sum += i; 26 | } 27 | } else { 28 | long step = (start + end) / 100; 29 | ArrayList subTasks = new ArrayList(); 30 | long pos = start; 31 | for (int i = 0; i < 100; i++) { 32 | long lastOne = pos + step; 33 | if (lastOne > end) 34 | lastOne = end; 35 | CountTask subTask = new CountTask(pos, lastOne); 36 | pos += step + 1; 37 | subTasks.add(subTask); 38 | subTask.fork(); 39 | } 40 | for (CountTask t : subTasks) { 41 | sum += t.join(); 42 | } 43 | } 44 | return sum; 45 | } 46 | 47 | public static void main(String[] args) { 48 | ForkJoinPool forkJoinPool = new ForkJoinPool(); 49 | CountTask task = new CountTask(0, 200000L); 50 | ForkJoinTask result = forkJoinPool.submit(task); 51 | try { 52 | long res = result.get(); 53 | System.out.println("sum=" + res); 54 | } catch (InterruptedException e) { 55 | e.printStackTrace(); 56 | } catch (ExecutionException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/ch4/s4/AtomicReferenceDemo.java: -------------------------------------------------------------------------------- 1 | package ch4.s4; 2 | 3 | import java.util.concurrent.atomic.AtomicReference; 4 | 5 | public class AtomicReferenceDemo { 6 | static AtomicReference money = new AtomicReference(); 7 | public static void main(String[] args) { 8 | money.set(19); 9 | for (int i = 0; i < 3; i++) { 10 | new Thread() { 11 | 12 | public void run() { 13 | while(true) { 14 | while (true) { 15 | Integer m = money.get(); 16 | if (m < 20) { 17 | if (money.compareAndSet(m, m + 20)) { 18 | System.out.println("余额小于20元,充值成功,余额:" + money.get() + "元"); 19 | break; 20 | } 21 | } else { 22 | // System.out.println("余额大于20元,无需充值"); 23 | break; 24 | } 25 | } 26 | } 27 | } 28 | }.start(); 29 | } 30 | 31 | new Thread(){ 32 | 33 | public void run() { 34 | for(int i=0;i<100;i++) { 35 | while (true) { 36 | Integer m = money.get(); 37 | if(m>10){ 38 | System.out.println("大于10元"); 39 | if(money.compareAndSet(m,m-10)){ 40 | System.out.println("成功消费10元,余额:"+money.get()); 41 | break; 42 | } 43 | }else{ 44 | System.out.println("没有足够的金额"); 45 | break; 46 | } 47 | } 48 | try { 49 | Thread.sleep(100); 50 | } catch (InterruptedException e) { 51 | e.printStackTrace(); 52 | } 53 | } 54 | } 55 | }.start(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/CyclicBarrierDemo.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.BrokenBarrierException; 5 | import java.util.concurrent.CyclicBarrier; 6 | 7 | public class CyclicBarrierDemo { 8 | public static class Soldier implements Runnable { 9 | private String soldier; 10 | private final CyclicBarrier cyclic; 11 | 12 | Soldier(CyclicBarrier cyclic, String soldier) { 13 | this.cyclic = cyclic; 14 | this.soldier = soldier; 15 | } 16 | 17 | 18 | public void run() { 19 | try { 20 | cyclic.await(); 21 | doWork(); 22 | cyclic.await(); 23 | } catch (InterruptedException e) { 24 | e.printStackTrace(); 25 | } catch (BrokenBarrierException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | 30 | public void doWork() { 31 | try { 32 | Thread.sleep(Math.abs(new Random().nextInt() % 10000)); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } 36 | System.out.println(soldier + "任务完成"); 37 | } 38 | } 39 | 40 | public static class BarrierRun implements Runnable { 41 | boolean flag; 42 | int N; 43 | 44 | BarrierRun(boolean flag, int N) { 45 | this.flag = flag; 46 | this.N = N; 47 | } 48 | 49 | 50 | public void run() { 51 | if (flag) { 52 | System.out.println("司令:【士兵" + N + "个,任务完成!】"); 53 | } else { 54 | System.out.println("司令:【士兵" + N + "个,集合完毕!】"); 55 | flag = true; 56 | } 57 | } 58 | } 59 | 60 | public static void main(String[] args) { 61 | final int N = 10; 62 | Thread[] allSoldiers = new Thread[N]; 63 | boolean flag = false; 64 | CyclicBarrier cyclic = new CyclicBarrier(N, new BarrierRun(flag, N)); 65 | System.out.println("集合队伍"); 66 | for (int i = 0; i < N; i++) { 67 | System.out.println("士兵" + i + "报道"); 68 | allSoldiers[i] = new Thread(new Soldier(cyclic, "士兵" + i)); 69 | allSoldiers[i].start(); 70 | } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/ch4/s3/ThreadLocalPerformance.java: -------------------------------------------------------------------------------- 1 | package ch4.s3; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.*; 5 | 6 | public class ThreadLocalPerformance { 7 | public static final int GEN_COUNT = 10000000; 8 | public static final int THREAD_COUNT = 4; 9 | static ExecutorService exe = Executors.newFixedThreadPool(THREAD_COUNT); 10 | public static Random rnd = new Random(123); 11 | 12 | public static ThreadLocal tRnd = new ThreadLocal(){ 13 | 14 | protected Random initialValue() { 15 | return new Random(123); 16 | } 17 | }; 18 | 19 | public static class RndTask implements Callable{ 20 | private int mode = 0; 21 | public RndTask(int mode){ 22 | this.mode = mode; 23 | } 24 | public Random getRandom(){ 25 | if(mode == 0){ 26 | return rnd; 27 | } else if (mode == 1){ 28 | return tRnd.get(); 29 | } else{ 30 | return null; 31 | } 32 | } 33 | 34 | public Long call() throws Exception { 35 | long b =System.currentTimeMillis(); 36 | for(long i=0;i[] futs = new Future[THREAD_COUNT]; 47 | for(int i=0;i t1 =new ThreadLocal(){ 12 | 13 | protected void finalize() throws Throwable { 14 | System.out.println(this.toString() + " is gc"); 15 | } 16 | }; 17 | static volatile CountDownLatch cd =new CountDownLatch(10000); 18 | public static class ParseDate implements Runnable{ 19 | int i=0; 20 | public ParseDate(int i){ 21 | this.i = i; 22 | } 23 | 24 | public void run() { 25 | try{ 26 | if(t1.get()==null){ 27 | t1.set(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"){ 28 | 29 | protected void finalize() throws Throwable { 30 | System.out.println(this.toString() + " is gc"); 31 | } 32 | }); 33 | System.out.println(Thread.currentThread().getId() + ":create SimpleDateFormat"); 34 | } 35 | Date t =t1.get().parse("2015-03-29 19:29:"+i%60); 36 | } catch (ParseException e) { 37 | e.printStackTrace(); 38 | } finally { 39 | cd.countDown(); 40 | } 41 | } 42 | } 43 | public static void main(String []args) throws InterruptedException { 44 | ExecutorService es = Executors.newFixedThreadPool(10); 45 | for(int i=0;i<10000;i++){ 46 | es.execute(new ParseDate(i)); 47 | } 48 | cd.wait(); 49 | System.out.println("mission complete!!"); 50 | t1=null; 51 | System.gc(); 52 | System.out.println("first GC complete!!"); 53 | t1= new ThreadLocal(); 54 | cd =new CountDownLatch(10000); 55 | for(int i=0;i<10000;i++){ 56 | es.execute(new ParseDate(i)); 57 | } 58 | cd.wait(); 59 | Thread.sleep(1000); 60 | System.gc(); 61 | System.out.println("second GC complete!!"); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/ReadWriteLockDemo.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.locks.Lock; 5 | import java.util.concurrent.locks.ReentrantLock; 6 | import java.util.concurrent.locks.ReentrantReadWriteLock; 7 | 8 | public class ReadWriteLockDemo { 9 | private static Lock lock = new ReentrantLock(); 10 | private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); 11 | private static Lock readLock = readWriteLock.readLock(); 12 | private static Lock writeLock = readWriteLock.writeLock(); 13 | private int value; 14 | 15 | public Object handleRead(Lock lock) throws InterruptedException { 16 | try { 17 | lock.lock(); 18 | Thread.sleep(1000); 19 | System.out.println("read success"); 20 | return value; 21 | } finally { 22 | lock.unlock(); 23 | } 24 | } 25 | 26 | public void handleWrite(Lock lock, int index) throws InterruptedException { 27 | try { 28 | lock.lock(); 29 | Thread.sleep(1000); 30 | value = index; 31 | System.out.println("write success"); 32 | } finally { 33 | lock.unlock(); 34 | } 35 | } 36 | 37 | public static void main(String[] args) { 38 | final ReadWriteLockDemo demo = new ReadWriteLockDemo(); 39 | Runnable readRunnable = new Runnable() { 40 | public void run() { 41 | try { 42 | // demo.handleRead(readLock); 43 | demo.handleRead(lock); 44 | } catch (InterruptedException e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | }; 49 | Runnable writeRunnable = new Runnable() { 50 | 51 | public void run() { 52 | try { 53 | // demo.handleWrite(writeLock, new Random().nextInt()); 54 | demo.handleWrite(lock, new Random().nextInt()); 55 | } catch (InterruptedException e) { 56 | e.printStackTrace(); 57 | } 58 | } 59 | }; 60 | 61 | for (int i = 0; i < 18; i++) { 62 | new Thread(readRunnable).start(); 63 | } 64 | 65 | for (int i = 18; i < 20; i++) { 66 | new Thread(writeRunnable).start(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/ch4/s4/AtomicStampedReferenceDemo.java: -------------------------------------------------------------------------------- 1 | package ch4.s4; 2 | 3 | import java.util.concurrent.atomic.AtomicStampedReference; 4 | 5 | public class AtomicStampedReferenceDemo { 6 | static AtomicStampedReference money = new AtomicStampedReference(19, 0); 7 | 8 | public static void main(String[] args) { 9 | for (int i = 0; i < 3; i++) { 10 | final int timestamp = money.getStamp(); 11 | new Thread() { 12 | 13 | public void run() { 14 | while (true) { 15 | while (true) { 16 | Integer m = money.getReference(); 17 | if (m < 20) { 18 | if (money.compareAndSet(m, m + 20, timestamp, timestamp + 1)) { 19 | System.out.println("余额小于20元,充值成功,余额:" + money.getReference() + "元"); 20 | break; 21 | } 22 | } else { 23 | // System.out.println("余额大于20元,无需充值"); 24 | break; 25 | } 26 | } 27 | } 28 | } 29 | }.start(); 30 | } 31 | 32 | new Thread() { 33 | 34 | public void run() { 35 | for (int i = 0; i < 100; i++) { 36 | while (true) { 37 | int timestamp = money.getStamp(); 38 | Integer m = money.getReference(); 39 | if (m > 10) { 40 | System.out.println("大于10元"); 41 | if (money.compareAndSet(m, m - 10, timestamp, timestamp + 1)) { 42 | System.out.println("成功消费10元,余额:" + money.getReference()); 43 | break; 44 | } 45 | } else { 46 | System.out.println("没有足够的金额"); 47 | break; 48 | } 49 | } 50 | try { 51 | Thread.sleep(100); 52 | } catch (InterruptedException e) { 53 | e.printStackTrace(); 54 | } 55 | } 56 | } 57 | }.start(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/ch3/s1/TryLock.java: -------------------------------------------------------------------------------- 1 | package ch3.s1; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | public class TryLock implements Runnable { 6 | // 这里书中没有提到,这儿使用static,所以创建两个TryLock对象才会共用lock1和lock2 7 | // 如果没有static会很快结束程序,因为使用的是自己的lock1和lock2不会互相锁住 8 | public static ReentrantLock lock1 = new ReentrantLock(); 9 | public static ReentrantLock lock2 = new ReentrantLock(); 10 | int lock; 11 | 12 | public TryLock(int lock) { 13 | this.lock = lock; 14 | } 15 | 16 | 17 | public void run() { 18 | if (lock == 1) { 19 | while (true) { 20 | if(lock1.tryLock()){ 21 | try { 22 | try { 23 | Thread.sleep(500); 24 | } catch (InterruptedException e) { 25 | e.printStackTrace(); 26 | } 27 | if (lock2.tryLock()) { 28 | try { 29 | System.out.println(Thread.currentThread().getId() + " my job done"); 30 | return; 31 | } finally { 32 | lock2.unlock(); 33 | } 34 | } 35 | }finally { 36 | lock1.unlock(); 37 | } 38 | } 39 | } 40 | } else { 41 | while (true) { 42 | if(lock2.tryLock()){ 43 | try { 44 | try { 45 | Thread.sleep(500); 46 | } catch (InterruptedException e) { 47 | e.printStackTrace(); 48 | } 49 | if (lock1.tryLock()) { 50 | try { 51 | System.out.println(Thread.currentThread().getId() + " my job done"); 52 | return; 53 | } finally { 54 | lock1.unlock(); 55 | } 56 | } 57 | }finally { 58 | lock2.unlock(); 59 | } 60 | } 61 | } 62 | } 63 | } 64 | 65 | public static void main(String [] args){ 66 | TryLock lock1 = new TryLock(1); 67 | TryLock lock2 = new TryLock(2); 68 | Thread t1 = new Thread(lock1); 69 | Thread t2 = new Thread(lock2); 70 | t1.start(); 71 | t2.start(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /notes/ch2.md: -------------------------------------------------------------------------------- 1 | ## 第2章 Java并行程序基础 29 2 | 3 | ### 2.1 有关线程你必须知道的事 29 4 | 5 | - 线程状态 6 | 7 | ```java 8 | public enum State{ 9 | NEW, 10 | RUNNABLE, 11 | BLOCKED, 12 | WAITING, 13 | TIMED_WAITING, 14 | TERMINATED 15 | } 16 | ``` 17 | 18 | ### 2.2 初始线程:线程的基本操作 32 19 | 20 | #### 2.2.1 新建线程 32 21 | 22 | - Thread类和Runnable类,Thread中的构造方法`public Thread(Runnable target)`,其中run函数如下: 23 | 24 | ```java 25 | public void run(){ 26 | if(target != null){ 27 | target.run(); 28 | } 29 | } 30 | ``` 31 | 32 | #### 2.2.2 终止线程 34 33 | 34 | - 终止线程的stop方法不建议使用,可能会导致数据不一致,可以使用内部设置函数来解决问题 35 | 36 | #### 2.2.3 线程中断 38 37 | 38 | ```java 39 | public void Thread.interrupt() //中断线程 40 | public boolean Thread.isInterrupted() //判断线程是否中断 41 | public static boolean Thread.interrupted() //判断是否中断,并清除中断状态 42 | ``` 43 | 44 | 在sleep时,如果来临中断,会进入中断异常,同时也会将标记位清空,所以异常处理那里经常要再次中断自己 45 | 46 | #### 2.2.4 等待(wait)和通知(notify) 41 47 | 48 | - wait会释放掉锁 49 | - [SimpleWN](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch2/SimpleWN.java) 50 | 51 | #### 2.2.5 挂起(suspend)和继续执行(resume)线程 44 52 | 53 | - suspend和resume不推荐使用,因为不会释放锁资源,查看jstack时可以使用jps查看pid 54 | - [BadSuspend](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch2/BadSuspend.java) 55 | 56 | #### 2.2.6 等待线程结束(join)和谦让(yield) 48 57 | 58 | - [JoinMain](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch2/JoinMain.java) 59 | 60 | ### 2.3 volatile与Java内存模型(JMM) 50 61 | 62 | - volatile无法保证原子性 63 | - [NoVisibility](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch2/NoVisibility.java) 64 | 65 | ### 2.4 分门别类的管理:线程组 52 66 | 67 | - [ThreadGroupName](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch2/ThreadGroupName.java) 68 | 69 | ### 2.5 驻守后台:守护线程(Daemon) 54 70 | 71 | - [DaemonDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch2/DaemonDemo.java) 72 | 73 | ### 2.6 先干重要的事:线程优先级 55 74 | 75 | - [PriorityDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch2/PriorityDemo.java) 76 | 77 | ### 2.7 线程安全的概念与synchronized 57 78 | 79 | - [AccountingVol](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch2/AccountingVol.java) 80 | - [AccountingSyncBad](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch2/AccountingSyncBad.java) 81 | 82 | ### 2.8 程序中的幽灵:隐蔽的错误 61 83 | 84 | #### 2.8.1 无提示的错误案例 61 85 | #### 2.8.2 并发下的ArrayList 62 86 | #### 2.8.3 并发下诡异的HashMap 63 87 | #### 2.8.4 初学者常见问题:错误的加锁 66 88 | 89 | ### 2.9 参考文献 68 -------------------------------------------------------------------------------- /notes/ch5.md: -------------------------------------------------------------------------------- 1 | ## 第5章 并行模式与算法 184 2 | 3 | ### 5.1 探讨单例模式 184 4 | 5 | - 频繁使用的对象省略new花费的时间 6 | - 减轻GC压力,缩短GC停顿时间 7 | - [Singleton](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s1/Singleton.java),demo有一个问题,创建和调用不是一致的 8 | - [LazySingleton](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s1/LazySingleton.java) 9 | - [StaticSingleton](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s1/StaticSingleton.java),内部类没被调用前不会被加载 10 | 11 | ### 5.2 不变模式 187 12 | 13 | - 不变模式的主要场景 14 | - 对象创建后,内部状态和数据不再发生变化 15 | - 对象需要共享,被多线程访问 16 | - 注意点 17 | - 去除setter以及一切修改属性的方法 18 | - 将所有属性私有,并设为final,确保数据只能被构造一次,类不能有子类 19 | - 确保没有子类可以重载修改他 20 | - 有一个可以创建完整对象的构造函数 21 | - [Product](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s2/Product.java),内部类没被调用前不会被加载 22 | - 基本数据类型和String类型是不变模式实现的 23 | 24 | ### 5.3 生产者-消费者模式 190 25 | 26 | - 共享内存缓存区,解耦,缓解时间差 27 | - [代码](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s3/Main.java) 28 | 29 | ### 5.4 高性能的生产者-消费者:无锁的实现 194 30 | 31 | - ConcurrentLinkedQueue是一个高性能的队列,BlockingQueue只是为了方便数据共享 32 | - ConcurrentLinkedQueue使用了CAS,现成的Disruptor实现了 33 | 34 | #### 5.4.1 无锁的缓存框架:Disruptor 195 35 | 36 | - LMAX公司开发 37 | - 使用了环形队列(RingBuffer) 38 | - 大小为2的整数次方 39 | 40 | #### 5.4.2 用Disruptor实现生产者-消费者案例 196 41 | 42 | - [代码](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s4/Main.java) 43 | 44 | #### 5.4.3 提高消费者的响应时间:选择合适的策略 199 45 | 46 | - BlockingWaitStrategy 47 | - SleepingWaitStrategy 48 | - YieldingWaitStrategy 49 | - BusySpinWaitStrategy 50 | 51 | #### 5.4.4 CPU Cache的优化:解决伪共享问题 200 52 | 53 | - 如果两个变量在同一个缓存行,其中一个被修改后另一个也会失效,所以要想办法通过占位来不让其在同一个缓存行 54 | - [代码](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s4/FalseSharing.java) 55 | - Disruptor的Sequence组件基本结构 56 | 57 | ```java 58 | class LhsPadding{ 59 | protected long p1, p2, p3, p4, p5, p6, p7; 60 | } 61 | 62 | class Value extends LhsPadding{ 63 | protected volatile long value; 64 | } 65 | 66 | class RhsPadding extends Value{ 67 | protected long p9, p10, p11, p12, p13, p14, p15; 68 | } 69 | 70 | public class Sequence extends RhsPadding{ 71 | //... 72 | } 73 | ``` 74 | 75 | 76 | ### 5.5 Future模式 204 77 | 78 | - 核心思想是异步调用 79 | 80 | #### 5.5.1 Future模式的主要角色 206 81 | 82 | |参与者|作用| 83 | |:---:|:---:| 84 | |Main|系统启动,调用Client发出请求| 85 | |Client|返回Data对象,立即返回FutureData,并开启ClientThread线程装配RealData| 86 | |Data|返回数据的接口| 87 | |FutureData|Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData| 88 | |RealData|真实数据,其构造是比较慢的| 89 | 90 | #### 5.5.2 Future模式的简单实现 207 91 | 92 | - [代码](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s5/s2/Main.java) 93 | 94 | #### 5.5.3 JDK中的Future模式 210 95 | 96 | - 主要的几个类:Runnable,Future,RunnableFuture,FutureTask,Sync,Callable,类图见书中 97 | - [代码](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s5/s3) 98 | 99 | ### 5.6 并行流水线 212 100 | 101 | - 并非所有的计算都可以改造成并发的形式 102 | - 不能直接并发的可以考虑改成流水线的形式 103 | - [代码](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s6) 104 | 105 | ### 5.7 并行搜索 216 106 | 107 | - 将数据按照期望的线程数进行分割 108 | - [代码](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch5/s7) 109 | 110 | ### 5.8 并行排序 218 111 | 112 | - 暂时没看懂,先跳过,之后回来读 113 | 114 | #### 5.8.1 分离数据相关性:奇偶交换排序 218 115 | #### 5.8.2 改进的插入排序:希尔排序 221 116 | 117 | ### 5.9 并行算法:矩阵乘法 226 118 | ### 5.10 准备好了再通知我:网络NIO 230 119 | 120 | - Java NIO是New IO的简称 121 | - 涉及的基础内容有通道(Channel)和缓冲区(Buffer),文件IO和网络IO 122 | 123 | #### 5.10.1 基于Socket的服务端的多线程模式 230 124 | #### 5.10.2 使用NIO进行网络编程 235 125 | #### 5.10.3 使用NIO来实现客户端 243 126 | 127 | ### 5.11 读完了再通知我:AIO 245 128 | 129 | #### 5.11.1 AIO EchoServer的实现 245 130 | #### 5.11.2 AIO Echo客户端实现 248 131 | 132 | ### 5.12 参考文献 249 -------------------------------------------------------------------------------- /notes/ch4.md: -------------------------------------------------------------------------------- 1 | ## 第4章 锁的优化及注意事项 138 2 | 3 | ### 4.1 有助于提高“锁”性能的几点建议 139 4 | 5 | #### 4.1.1 减小锁持有时间 139 6 | 7 | - JDK1.7源代码:[Pattern](https://github.com/guanpengchn/JDK/blob/master/JDK1.7/src/java/util/regex/Pattern.java) 8 | 9 | #### 4.1.2 减小锁粒度 140 10 | 11 | - 对整个HashMap加锁粒度过大,对于ConcurrentHashMap内部细分若干个HashMap,称之为段,被分成16个段 12 | - 现根据hashcode得到应该存放到哪个段中,然后对该段加锁 13 | - JDK8中改变了实现方式,使用CAS来做实现,区别可见[文章](https://blog.csdn.net/Gavin__Zhou/article/details/76792071) 14 | 15 | #### 4.1.3 读写分离锁来替换独占锁 142 16 | 17 | - [ReadWriteLock](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/ReadWriteLockDemo.java) 18 | 19 | #### 4.1.4 锁分离 142 20 | 21 | - 在LinkedBlockingQueue中,take和put函数分别作用于队列的前端和尾端,不冲突,如果使用独占锁就无法并发,所以实现中使用了两把锁 22 | - JDK1.7源代码:[LinkedBlockingQueue](https://github.com/guanpengchn/JDK/blob/master/JDK1.7/src/java/util/concurrent/LinkedBlockingQueue.java) 23 | 24 | #### 4.1.5 锁粗化 144 25 | 26 | - 虚拟机在遇到一连串的锁请求和释放,会优化合并成一次,叫做锁的粗化 27 | - 在循环内使用锁往往可以考虑优化成在循环外 28 | 29 | ### 4.2 Java虚拟机对锁优化所做的努力 146 30 | 31 | #### 4.2.1 锁偏向 146 32 | 33 | - 如果一个线程获得了锁,就进入了偏向模式,之后该线程再去连续申请就无须做其他操作 34 | - 但是如果不同线程来回切换,效果反而差,不如不开启锁偏向 35 | - Java虚拟机参数:-XX:+IseBiasedLocking 36 | 37 | #### 4.2.2 轻量级锁 146 38 | 39 | - 偏向锁升级为轻量级锁,轻量级锁,升级为重量级锁 40 | - 这里书中写的比较简略,可以看文章[java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁](https://blog.csdn.net/zqz_zqz/article/details/70233767) 41 | 42 | #### 4.2.3 自旋锁 146 43 | 44 | - 虚拟机假设当前线程还可以获得锁,不马上挂起线程,让当前线程做几个空循环,如果能获得就进入临界区,如果不行则挂起 45 | 46 | #### 4.2.4 锁消除 146 47 | 48 | - 在编译过程中,去掉不可能共享资源的锁,比如局部变量 49 | - 锁消除的一项关键技术叫做逃逸分析 50 | - 逃逸分析必须在-server模式下,虚拟机参数:-XX:+DoEscapeAnalysis打开逃逸分析,-XX:+EliminateLocks打开锁消除 51 | 52 | ### 4.3 人手一支笔:ThreadLocal 147 53 | 54 | #### 4.3.1 ThreadLocal的简单使用 148 55 | 56 | - 这个demo测试没有ThreadLocal,仅仅是对象在run内部new出来也行呀,不是很懂 57 | - [ThreadLocalDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch4/s3/ThreadLocalDemo.java) 58 | 59 | #### 4.3.2 ThreadLocal的实现原理 149 60 | 61 | - ThreadLocalMap我在jdk1.8下运行不出效果来,作者在书中也提到了,二者实现方式不同 62 | - [ThreadLocalDemo_Gc](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch4/s3/ThreadLocalDemo_Gc.java) 63 | - WeakHashMap和HashMap的区别可以见该[文章](http://mzlly999.iteye.com/blog/1126049)和代码[WeakVsHashMap](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch4/s3/WeakVsHashMap.java) 64 | - 理解弱引用和强引用概念,可参考[Java 7之基础 - 强引用、弱引用、软引用、虚引用](https://blog.csdn.net/mazhimazh/article/details/19752475) 65 | 66 | #### 4.3.3 对性能有何帮助 155 67 | 68 | - 见下面demo可得ThreadLocal的效率还是很高的 69 | - [ThreadLocalPerformance](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch4/s3/ThreadLocalPerformance.java) 70 | 71 | ### 4.4 无锁 157 72 | 73 | - 无锁策略使用一种叫做比较交换的技术(CAS Compare And Swap) 74 | 75 | #### 4.4.1 与众不同的并发策略:比较交换(CAS) 158 76 | 77 | - 天生免疫死锁,没有锁竞争和线程切换的开销 78 | - CAS(V,E,N),V表示要更新的变量,E表示预期值,N表示新值,当V=E时,才会将V值设为N,如果不相等则该线程被告知失败,可以再次尝试 79 | - 硬件层面现代处理器已经支持原子化的CAS指令 80 | 81 | #### 4.4.2 无锁的线程安全整数:AtomicInteger 159 82 | 83 | - atomic包中实现了直接使用CAS的线程安全类型 84 | - [AtomicIntegerDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch4/s4/AtomicIntegerDemo.java) 85 | 86 | #### 4.4.3 Java中的指针:Unsafe类 161 87 | 88 | - native方法是不用java实现的 89 | - [compareAndSet](https://github.com/guanpengchn/JDK/blob/master/JDK1.7/src/java/util/concurrent/atomic/AtomicInteger.java#L134-L136) 90 | - Unsafe类在rt.jar中,jdk无法找到 91 | - JDK开发人员并不希望大家使用Unsafe类,下面的代码,会检查调用getUnsafe函数的类,如果这个类的ClassLoader不为空,直接抛出异常拒绝工作,这使得自己的程序无法直接调用Unsafe类 92 | 93 | ```java 94 | public static Unsafe getUnsafe() { 95 | Class cc = Reflection.getCallerClass(); 96 | if (cc.getClassLoader() != null) 97 | throw new SecurityException("Unsafe"); 98 | return theUnsafe; 99 | } 100 | ``` 101 | 102 | - 注意:根据Java类加载器的原理,应用程序的类由App Loader加载,而系统核心的类,如rt.jar中的由Bootstrap类加载器加载。Bootstrap加载器没有java对象的对象,因此试图获得该加载器会返回null,所以当一个类的类加载器为null时,说明是由Bootstrap加载的,这个类也极可能是rt.jar中的类 103 | 104 | #### 4.4.4 无锁的对象引用:AtomicReference 162 105 | 106 | - AtomicInteger是对整数的封装,AtomicReference是对对象的封装 107 | - 运行下面demo可以见到错误,进行了多次充值,原因是状态可能不同,但是值却可能相同,所以不应该用值来判断状态 108 | - [AtomicReferenceDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch4/s4/AtomicReferenceDemo.java) 109 | 110 | #### 4.4.5 带有时间戳的对象引用:AtomicStampedReference 165 111 | 112 | - 对象值和时间戳必须都一样才能修改成功,所以只会充值一次 113 | - [AtomicStampedReferenceDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch4/s4/AtomicStampedReferenceDemo.java) 114 | 115 | #### 4.4.6 数组也能无锁:AtomicIntegerArray 168 116 | 117 | - [AtomicIntegerArrayDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch4/s4/AtomicIntegerArrayDemo.java) 118 | 119 | #### 4.4.7 让普通变量也享受原子操作:AtomicIntegerFieldUpdater 169 120 | 121 | - 可以包装普通变量,让其也具有原子操作 122 | - [AtomicIntegerFieldUpdaterDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch4/s4/AtomicIntegerFieldUpdaterDemo.java) 123 | - 变量必须可见,不能为private 124 | - 为确保变量被正确读取,需要有volatile 125 | - CAS通过偏移量赋值,不支持static(Unsafe, objectFieldOffset不支持静态变量) 126 | 127 | #### 4.4.8 挑战无锁算法:无锁的Vector实现 171 128 | 129 | - N_BUCKET为30,相当于有30个数组,第一个数组大小FIRST_BUCKET_SIZE为8,但是Vector之后会不断翻倍,第二个数组就是16个,最终能2^33左右 130 | - 这段比较复杂,多看 131 | 132 | #### 4.4.9 让线程之间互相帮助:细看SynchronousQueue的实现 176 133 | 134 | ### 4.5 有关死锁的问题 179 135 | 136 | - [DeadLock](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch4/s5/DeadLock.java) 137 | 138 | ### 4.6 参考文献 183 -------------------------------------------------------------------------------- /notes/ch6.md: -------------------------------------------------------------------------------- 1 | ## 第6章 Java 8与并发 251 2 | 3 | ### 6.1 Java 8的函数式编程简介 251 4 | 5 | #### 6.1.1 函数作为一等公民 252 6 | 7 | - 函数可以作为另外一个函数的返回值 8 | 9 | #### 6.1.2 无副作用 252 10 | 11 | - 函数的副作用指的是函数在调用过程中,除了给出了返回值外,还修改了函数外部的状态 12 | - 函数的副作用应该被尽量避免 13 | - 显示函数指函数与外界交换数据的唯一渠道就是参数和返回值,显示函数不会去读取或者修改函数的外部状态 14 | 15 | #### 6.1.3 申明式的(Declarative) 253 16 | 17 | - 函数式编程是申明式的编程方式 18 | - [Example1](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s1/Example1.java) 19 | 20 | #### 6.1.4 不变的对象 254 21 | 22 | - [Example2](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s1/Example2.java) 23 | 24 | #### 6.1.5 易于并行 254 25 | 26 | - 由于对象都处于不变的状态,因此函数式编程更加易于并行,这样没有同步和锁机制,性能也会比较好 27 | 28 | #### 6.1.6 更少的代码 254 29 | 30 | - [Example3](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s1/Example3.java) 31 | 32 | ### 6.2 函数式编程基础 255 33 | 34 | #### 6.2.1 FunctionalInterface注释 255 35 | 36 | - 函数式接口是只定义单一抽象方法的接口 37 | - 只能有一个抽象方法,而不是只能有一个方法,任何被java.lang.Object实现的方法都不能视为抽象方法 38 | 39 | #### 6.2.2 接口默认方法 256 40 | 41 | - Java8之前的版本,接口只能包含抽象方法,但从Java8之后,接口也可以包含若干个实例方法 42 | - default关键字可以在接口内定义实例方法,这个方法并非抽象方法,而是拥有特定逻辑的具体实例方法 43 | - Comparator接口新增了若干个默认方法 44 | 45 | #### 6.2.3 lambda表达式 259 46 | 47 | - 外部的num在lambda表达式中必须申明为final,如果不申明Java8也会默认处理成final 48 | - [Example1](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s2/Example1.java) 49 | 50 | #### 6.2.4 方法引用 260 51 | 52 | |类型|使用方法| 53 | |:---:|:---:| 54 | |静态方法引用|ClassName::methodName| 55 | |实例上的实例方法引用|instanceReference::methodName| 56 | |超类上的实例方法引用|super::methodName| 57 | |类型上的实例方法引用|ClassName::methodName| 58 | |构造方法引用|Class::new| 59 | |数组构造方法引用|TypeName[]::new| 60 | 61 | - [InstanceMethodRef](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s2/InstanceMethodRef.java) 62 | - [BadMethodRef](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s2/BadMethodRef.java) 63 | - [BadMethodRef](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s2/BadMethodRef.java) 64 | 65 | ### 6.3 一步一步走入函数式编程 263 66 | 67 | - forEach原始实现 68 | 69 | ```java 70 | static int[] arr = {1,2,3,4,5,6,7,8,9,10}; 71 | 72 | public static void main(String[] args){ 73 | Arrays.stream(arr).forEach(new IntConsumer(){ 74 | @Override 75 | public void accept(int value){ 76 | System.out.println(value); 77 | } 78 | }); 79 | } 80 | ``` 81 | 82 | - 由于forEach()函数的参数是可以从上下文推导出来的,所以可以改写如下 83 | 84 | ```java 85 | static int[] arr = {1,2,3,4,5,6,7,8,9,10}; 86 | 87 | public static void main(String[] args){ 88 | Arrays.stream(arr).forEach((final int x)->{ 89 | System.out.println(x); 90 | }); 91 | } 92 | ``` 93 | 94 | - 参数类型也可以推导,进而简化如下 95 | 96 | ```java 97 | static int[] arr = {1,2,3,4,5,6,7,8,9,10}; 98 | 99 | public static void main(String[] args){ 100 | Arrays.stream(arr).forEach((x)->{ 101 | System.out.println(x); 102 | }); 103 | } 104 | ``` 105 | 106 | - 放到一行 107 | 108 | ```java 109 | static int[] arr = {1,2,3,4,5,6,7,8,9,10}; 110 | 111 | public static void main(String[] args){ 112 | Arrays.stream(arr).forEach((x)->System.out.println(x)); 113 | } 114 | ``` 115 | 116 | - lambda表达式可以使用更流畅的流式API对组件进行自由的装配 117 | 118 | ```java 119 | static int[] arr={1,3,4,5,6,7,8,9,10}; 120 | 121 | public static void main(String[] args){ 122 | IntConsumer outprintln=System.out::println; 123 | IntConsumer errprintln=System.err::println; 124 | Arrays.stream(arr).forEach(outprintln.andThen(errprintln)); 125 | } 126 | ``` 127 | 128 | ### 6.4 并行流与并行排序 267 129 | 130 | #### 6.4.1 使用并行流过滤数据 267 131 | 132 | - [PrimeUtil](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s4/PrimeUtil.java) 133 | 134 | #### 6.4.2 从集合得到并行流 268 135 | 136 | ```java 137 | List ss =new ArrayList(); 138 | double ave=ss.stream().mapToInt(s->s.score).average().getAsDouble(); 139 | 140 | double ave=ss.parallelStream().mapToInt(s->s.score).average().getAsDouble(); 141 | ``` 142 | 143 | #### 6.4.3 并行排序 268 144 | 145 | - 并行排序 146 | 147 | ```java 148 | int []arr=new int[10000000]; 149 | Arrays.parallelSort(arr); 150 | ``` 151 | 152 | - 并行随机值 153 | 154 | ```java 155 | Random r =new Random(); 156 | Arrays.setAll(arr,(i)->r.nextInt()); 157 | 158 | Arrays.parallelSetAll(arr,(i)->r.nextInt()); 159 | ``` 160 | 161 | ### 6.5 增强的Future:CompletableFuture 269 162 | 163 | - 为函数式编程中的流式调用准备 164 | 165 | #### 6.5.1 完成了就通知我 269 166 | 167 | - [Example1](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s5/Example1.java) 168 | 169 | #### 6.5.2 异步执行任务 270 170 | 171 | - [Example2](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s5/Example2.java) 172 | 173 | #### 6.5.3 流式调用 272 174 | 175 | - [Example3](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s5/Example3.java) 176 | 177 | #### 6.5.4 CompletableFuture中的异常处理 272 178 | 179 | - [Example4](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s5/Example4.java) 180 | 181 | #### 6.5.5 组合多个CompletableFuture 273 182 | 183 | - [Example5](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s5/Example5.java) 184 | - [Example6](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s5/Example6.java) 185 | 186 | ### 6.6 读写锁的改进:StampedLock 274 187 | 188 | #### 6.6.1 StampedLock使用示例 275 189 | 190 | - [Point](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s6/Point.java) 191 | 192 | #### 6.6.2 StampedLock的小陷阱 276 193 | 194 | - [StampedLockCPUDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s6/StampedLockCPUDemo.java) 195 | 196 | #### 6.6.3 有关StampedLock的实现思想 278 197 | 198 | - 内部实现基于CLH锁,CLH是一种自旋锁,保证没有饥饿发生并且保证FIFO的服务顺序 199 | 200 | ### 6.7 原子类的增强 281 201 | 202 | #### 6.7.1 更快的原子类:LongAdder 281 203 | 204 | - 热点分离,类似于ConcurrentHashMap 205 | - 性能更好,好于AtomicInteger,而且使用了@sun.misc.Contended来避免伪共享 206 | 207 | #### 6.7.2 LongAdder的功能增强版:LongAccumulator 287 208 | 209 | - [LongAccumulatorDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch6/s7/LongAccumulatorDemo.java) 210 | 211 | ### 6.8 参考文献 288 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 《实战Java高并发程序设计》笔记和源码 2 | 3 | ## 笔记 4 | 5 | - 《实战Java高并发程序设计》中有很多代码范例,适合初学者通过实践入门并发编程,这本书有个问题就是前面的代码都用JDK7,第六章开始又用JDK8了 6 | - 笔者做了相关笔记并整理源代码,欢迎交流和 [Star](https://github.com/guanpengchn/java-concurrent-programming) 7 | - 由于除了jdk外,需要引入第三方包,故而使用maven来进行包管理,建议运行代码前安装好maven环境 8 | - 笔记在 [notes](https://github.com/guanpengchn/java-concurrent-programming/blob/master/notes),源代码在 [src/main/java](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java) 9 | - 如有需要电子书,可去我的repo中访问[awesome-books](https://github.com/guanpengchn/awesome-books)仓库下载 10 | - part-部,chapter-章,section-节,paragraph/fragment/segment-完整的一段,passage-篇 11 | - 笔记中使用的JDK源代码[仓库](https://github.com/guanpengchn/JDK),fork于[zxiaofan的JDK仓库](https://github.com/zxiaofan/JDK) 12 | - [彻底删除git中的大文件](https://www.jianshu.com/p/780161d32c8e) 13 | 14 | ## 书籍概况 15 | 16 | - 作者: 葛一鸣 / 郭超 17 | - 出版社: 电子工业出版社 18 | - 出版年: 2015-11 19 | - 页数: 352 20 | - 定价: 69.00元 21 | - ISBN: 9787121273049 22 | 23 | ## 目录 24 | 25 | - 第1章 走入并行世界 1 26 | 27 | - 1.1 何去何从的并行计算 1 28 | 29 | - 1.1.1 忘掉那该死的并行 2 30 | - 1.1.2 可怕的现实:摩尔定律的失效 4 31 | - 1.1.3 柳暗花明:不断地前进 5 32 | - 1.1.4 光明或是黑暗 6 33 | 34 | - 1.2 你必须知道的几个概念 6 35 | 36 | - 1.2.1 同步(Synchronous)和异步(Asynchronous) 7 37 | - 1.2.2 并发(Concurrency)和并行(Parallelism) 8 38 | - 1.2.3 临界区 9 39 | - 1.2.4 阻塞(Blocking)和非阻塞(Non-Blocking) 9 40 | - 1.2.5 死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock) 9 41 | 42 | - 1.3 并发级别 11 43 | 44 | - 1.3.1 阻塞(Blocking) 11 45 | - 1.3.2 无饥饿(Starvation-Free) 11 46 | - 1.3.3 无障碍(Obstruction-Free) 12 47 | - 1.3.4 无锁(Lock-Free) 12 48 | - 1.3.5 无等待(Wait-Free) 13 49 | 50 | - 1.4 有关并行的两个重要定律 13 51 | 52 | - 1.4.1 Amdahl定律 13 53 | - 1.4.2 Gustafson定律 16 54 | - 1.4.3 Amdahl定律和Gustafson定律是否相互矛盾 16 55 | 56 | - 1.5 回到Java:JMM 17 57 | 58 | - 1.5.1 原子性(Atomicity) 18 59 | - 1.5.2 可见性(Visibility) 20 60 | - 1.5.3 有序性(Ordering) 22 61 | - 1.5.4 哪些指令不能重排:Happen-Before规则 27 62 | 63 | - 1.6 参考文献 27 64 | 65 | - 第2章 Java并行程序基础 29 66 | 67 | - 2.1 有关线程你必须知道的事 29 68 | - 2.2 初始线程:线程的基本操作 32 69 | 70 | - 2.2.1 新建线程 32 71 | - 2.2.2 终止线程 34 72 | - 2.2.3 线程中断 38 73 | - 2.2.4 等待(wait)和通知(notify) 41 74 | - 2.2.5 挂起(suspend)和继续执行(resume)线程 44 75 | - 2.2.6 等待线程结束(join)和谦让(yield) 48 76 | 77 | - 2.3 volatile与Java内存模型(JMM) 50 78 | - 2.4 分门别类的管理:线程组 52 79 | - 2.5 驻守后台:守护线程(Daemon) 54 80 | - 2.6 先干重要的事:线程优先级 55 81 | - 2.7 线程安全的概念与synchronized 57 82 | - 2.8 程序中的幽灵:隐蔽的错误 61 83 | 84 | - 2.8.1 无提示的错误案例 61 85 | - 2.8.2 并发下的ArrayList 62 86 | - 2.8.3 并发下诡异的HashMap 63 87 | - 2.8.4 初学者常见问题:错误的加锁 66 88 | 89 | - 2.9 参考文献 68 90 | 91 | - 第3章 JDK并发包 70 92 | 93 | - 3.1 多线程的团队协作:同步控制 70 94 | 95 | - 3.1.1 synchronized的功能扩展:重入锁 71 96 | - 3.1.2 重入锁的好搭档:Condition条件 80 97 | - 3.1.3 允许多个线程同时访问:信号量(Semaphore) 83 98 | - 3.1.4 ReadWriteLock读写锁 85 99 | - 3.1.5 倒计时器:CountDownLatch 87 100 | - 3.1.6 循环栅栏:CyclicBarrier 89 101 | - 3.1.7 线程阻塞工具类:LockSupport 92 102 | 103 | - 3.2 线程复用:线程池 95 104 | 105 | - 3.2.1 什么是线程池 96 106 | - 3.2.2 不要重复发明轮子:JDK对线程池的支持 97 107 | - 3.2.3 刨根究底:核心线程池的内部实现 102 108 | - 3.2.4 超负载了怎么办:拒绝策略 106 109 | - 3.2.5 自定义线程创建:ThreadFactory 109 110 | - 3.2.6 我的应用我做主:扩展线程池 110 111 | - 3.2.7 合理的选择:优化线程池线程数量 112 112 | - 3.2.8 堆栈去哪里了:在线程池中寻找堆栈 113 113 | - 3.2.9 分而治之:Fork/Join框架 117 114 | 115 | - 3.3 不要重复发明轮子:JDK的并发容器 121 116 | 117 | - 3.3.1 超好用的工具类:并发集合简介 121 118 | - 3.3.2 线程安全的HashMap 122 119 | - 3.3.3 有关List的线程安全 123 120 | - 3.3.4 高效读写的队列:深度剖析ConcurrentLinkedQueue 123 121 | - 3.3.5 高效读取:不变模式下的CopyOnWriteArrayList 129 122 | - 3.3.6 数据共享通道:BlockingQueue 130 123 | - 3.3.7 随机数据结构:跳表(SkipList) 134 124 | 125 | - 3.4 参考资料 136 126 | 127 | - 第4章 锁的优化及注意事项 138 128 | 129 | - 4.1 有助于提高“锁”性能的几点建议 139 130 | 131 | - 4.1.1 减小锁持有时间 139 132 | - 4.1.2 减小锁粒度 140 133 | - 4.1.3 读写分离锁来替换独占锁 142 134 | - 4.1.4 锁分离 142 135 | - 4.1.5 锁粗化 144 136 | 137 | - 4.2 Java虚拟机对锁优化所做的努力 146 138 | 139 | - 4.2.1 锁偏向 146 140 | - 4.2.2 轻量级锁 146 141 | - 4.2.3 自旋锁 146 142 | - 4.2.4 锁消除 146 143 | 144 | - 4.3 人手一支笔:ThreadLocal 147 145 | 146 | - 4.3.1 ThreadLocal的简单使用 148 147 | - 4.3.2 ThreadLocal的实现原理 149 148 | - 4.3.3 对性能有何帮助 155 149 | 150 | - 4.4 无锁 157 151 | 152 | - 4.4.1 与众不同的并发策略:比较交换(CAS) 158 153 | - 4.4.2 无锁的线程安全整数:AtomicInteger 159 154 | - 4.4.3 Java中的指针:Unsafe类 161 155 | - 4.4.4 无锁的对象引用:AtomicReference 162 156 | - 4.4.5 带有时间戳的对象引用:AtomicStampedReference 165 157 | - 4.4.6 数组也能无锁:AtomicIntegerArray 168 158 | - 4.4.7 让普通变量也享受原子操作:AtomicIntegerFieldUpdater 169 159 | - 4.4.8 挑战无锁算法:无锁的Vector实现 171 160 | - 4.4.9 让线程之间互相帮助:细看SynchronousQueue的实现 176 161 | 162 | - 4.5 有关死锁的问题 179 163 | - 4.6 参考文献 183 164 | 165 | - 第5章 并行模式与算法 184 166 | 167 | - 5.1 探讨单例模式 184 168 | - 5.2 不变模式 187 169 | - 5.3 生产者-消费者模式 190 170 | - 5.4 高性能的生产者-消费者:无锁的实现 194 171 | 172 | - 5.4.1 无锁的缓存框架:Disruptor 195 173 | - 5.4.2 用Disruptor实现生产者-消费者案例 196 174 | - 5.4.3 提高消费者的响应时间:选择合适的策略 199 175 | - 5.4.4 CPU Cache的优化:解决伪共享问题 200 176 | 177 | - 5.5 Future模式 204 178 | 179 | - 5.5.1 Future模式的主要角色 206 180 | - 5.5.2 Future模式的简单实现 207 181 | - 5.5.3 JDK中的Future模式 210 182 | 183 | - 5.6 并行流水线 212 184 | - 5.7 并行搜索 216 185 | - 5.8 并行排序 218 186 | 187 | - 5.8.1 分离数据相关性:奇偶交换排序 218 188 | - 5.8.2 改进的插入排序:希尔排序 221 189 | 190 | - 5.9 并行算法:矩阵乘法 226 191 | - 5.10 准备好了再通知我:网络NIO 230 192 | 193 | - 5.10.1 基于Socket的服务端的多线程模式 230 194 | - 5.10.2 使用NIO进行网络编程 235 195 | - 5.10.3 使用NIO来实现客户端 243 196 | 197 | - 5.11 读完了再通知我:AIO 245 198 | 199 | - 5.11.1 AIO EchoServer的实现 245 200 | - 5.11.2 AIO Echo客户端实现 248 201 | 202 | - 5.12 参考文献 249 203 | 204 | - 第6章 Java 8与并发 251 205 | 206 | - 6.1 Java 8的函数式编程简介 251 207 | 208 | - 6.1.1 函数作为一等公民 252 209 | - 6.1.2 无副作用 252 210 | - 6.1.3 申明式的(Declarative) 253 211 | - 6.1.4 不变的对象 254 212 | - 6.1.5 易于并行 254 213 | - 6.1.6 更少的代码 254 214 | 215 | - 6.2 函数式编程基础 255 216 | 217 | - 6.2.1 FunctionalInterface注释 255 218 | - 6.2.2 接口默认方法 256 219 | - 6.2.3 lambda表达式 259 220 | - 6.2.4 方法引用 260 221 | 222 | - 6.3 一步一步走入函数式编程 263 223 | - 6.4 并行流与并行排序 267 224 | 225 | - 6.4.1 使用并行流过滤数据 267 226 | - 6.4.2 从集合得到并行流 268 227 | - 6.4.3 并行排序 268 228 | 229 | - 6.5 增强的Future:CompletableFuture 269 230 | 231 | - 6.5.1 完成了就通知我 269 232 | - 6.5.2 异步执行任务 270 233 | - 6.5.3 流式调用 272 234 | - 6.5.4 CompletableFuture中的异常处理 272 235 | - 6.5.5 组合多个CompletableFuture 273 236 | 237 | - 6.6 读写锁的改进:StampedLock 274 238 | 239 | - 6.6.1 StampedLock使用示例 275 240 | - 6.6.2 StampedLock的小陷阱 276 241 | - 6.6.3 有关StampedLock的实现思想 278 242 | 243 | - 6.7 原子类的增强 281 244 | 245 | - 6.7.1 更快的原子类:LongAdder 281 246 | - 6.7.2 LongAdder的功能增强版:LongAccumulator 287 247 | 248 | - 6.8 参考文献 288 249 | 250 | - 第7章 使用Akka构建高并发程序 289 251 | 252 | - 7.1 新并发模型:Actor 290 253 | - 7.2 Akka之Hello World 290 254 | - 7.3 有关消息投递的一些说明 293 255 | - 7.4 Actor的生命周期 295 256 | - 7.5 监督策略 298 257 | - 7.6 选择Actor 303 258 | - 7.7 消息收件箱(Inbox) 303 259 | - 7.8 消息路由 305 260 | - 7.9 Actor的内置状态转换 308 261 | - 7.10 询问模式:Actor中的Future 311 262 | - 7.11 多个Actor同时修改数据:Agent 313 263 | - 7.12 像数据库一样操作内存数据:软件事务内存 316 264 | - 7.13 一个有趣的例子:并发粒子群的实现 319 265 | 266 | - 7.13.1 什么是粒子群算法 320 267 | - 7.13.2 粒子群算法的计算过程 320 268 | - 7.13.3 粒子群算法能做什么 322 269 | - 7.13.4 使用Akka实现粒子群 323 270 | 271 | - 7.14 参考文献 330 272 | 273 | - 第8章 并行程序调试 331 274 | 275 | - 8.1 准备实验样本 331 276 | - 8.2 正式起航 332 277 | - 8.3 挂起整个虚拟机 334 278 | - 8.4 调试进入ArrayList内部 336 279 | -------------------------------------------------------------------------------- /notes/ch3.md: -------------------------------------------------------------------------------- 1 | ## 第3章 JDK并发包 70 2 | 3 | ### 3.1 多线程的团队协作:同步控制 70 4 | 5 | #### 3.1.1 synchronized的功能扩展:重入锁 71 6 | 7 | - [ReenterLock](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/ReenterLock.java) 8 | - 可重入锁代表着一个线程可以多次获得同一把锁 9 | - 中断响应,[IntLock](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/IntLock.java) 10 | - 锁申请等待限时,[TimeLock](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/TimeLock.java) 11 | - 不带参数的[TryLock](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/TryLock.java) 12 | - 公平锁需要维护一个有序队列,成本高,默认是非公平锁,[FairLock](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/FairLock.java) 13 | 14 | 重入锁的实现主要包含三个要素: 15 | 16 | - 原子状态,CAS 17 | - 等待队列 18 | - 阻塞原语park()和unpark() 19 | 20 | #### 3.1.2 重入锁的好搭档:Condition条件 80 21 | 22 | - wait和notify是和synchronize合作使用的,condition是和重入锁相关联的,[ReenterLockCondition](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/ReenterLockCondition.java) 23 | 24 | #### 3.1.3 允许多个线程同时访问:信号量(Semaphore) 83 25 | 26 | - [SemapDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/SemapDemo.java) 27 | 28 | #### 3.1.4 ReadWriteLock读写锁 85 29 | 30 | - 实践了一下果然速度差距相当大 31 | - [ReadWriteLockDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/ReadWriteLockDemo.java) 32 | 33 | #### 3.1.5 倒计时器:CountDownLatch 87 34 | 35 | - [CountDownLatchDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/CountDownLatchDemo.java) 36 | 37 | #### 3.1.6 循环栅栏:CyclicBarrier 89 38 | 39 | - 这个理解起来难度大一些 40 | - [CyclicBarrierDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/CyclicBarrierDemo.java) 41 | 42 | #### 3.1.7 线程阻塞工具类:LockSupport 92 43 | 44 | - LockSupport的park和unpark函数,和suspend和resume函数比,不存在先后顺序,也就不会由于先resume后suspend导致程序死掉 45 | - 和信号量的区别是它只有一个许可,而信号量可以有多个 46 | - [LockSupportDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/LockSupportDemo.java) 47 | - [LockSupportIntDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s1/LockSupportIntDemo.java) 48 | 49 | ### 3.2 线程复用:线程池 95 50 | 51 | #### 3.2.1 什么是线程池 96 52 | #### 3.2.2 不要重复发明轮子:JDK对线程池的支持 97 53 | 54 | - 类图要好好看看,建议阅读jdk源代码了解下关系,整理如下: 55 | - ExecutorService继承了Executor 56 | - AbstractExecutorService实现了ExecutorService接口 57 | - Executors生成了ThreadPoolExecutor 58 | 59 | - Executors中包含的一部分线程池类型: 60 | - newFixedThreadPool,[ThreadPoolDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s2/ThreadPoolDemo.java) 61 | - newSingleThreadExecutor 62 | - newCachedThreadPool 63 | - newSingleThreadScheduledExecutor 64 | - newScheduledThreadPool 65 | - FixedRate是从上一个任务开始后计时,[ScheduledExecutorServiceDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s2/ScheduledExecutorServiceDemo.java) 66 | - FixedDelay是从上一个任务结束后计时 67 | 68 | #### 3.2.3 刨根究底:核心线程池的内部实现 102 69 | 70 | - 均使用ThreadPoolExecutor实现,最全的构造函数如下 71 | 72 | ```java 73 | public ThreadPoolExecutor(int corePoolSize, 74 | int maximumPoolSize, 75 | long keepAliveTime, 76 | TimeUnit unit, 77 | BlockingQueue workQueue, 78 | RejectedExecutionHandler handler) { 79 | this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, 80 | Executors.defaultThreadFactory(), handler); 81 | } 82 | ``` 83 | 84 | workQueue和handler需要特别理解一下,核心执行代码如下: 85 | 86 | ```java 87 | public void execute(Runnable command) { 88 | if (command == null) 89 | throw new NullPointerException(); 90 | int c = ctl.get(); 91 | if (workerCountOf(c) < corePoolSize) { 92 | if (addWorker(command, true)) 93 | return; 94 | c = ctl.get(); 95 | } 96 | if (isRunning(c) && workQueue.offer(command)) { 97 | int recheck = ctl.get(); 98 | if (! isRunning(recheck) && remove(command)) 99 | reject(command); 100 | else if (workerCountOf(recheck) == 0) 101 | addWorker(null, false); 102 | } 103 | else if (!addWorker(command, false)) 104 | reject(command); 105 | } 106 | ``` 107 | 108 | #### 3.2.4 超负载了怎么办:拒绝策略 106 109 | 110 | - 四种系统定义的拒绝策略代码 111 | 112 | ```java 113 | public static class CallerRunsPolicy implements RejectedExecutionHandler { 114 | public CallerRunsPolicy() { } 115 | public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 116 | if (!e.isShutdown()) { 117 | r.run(); 118 | } 119 | } 120 | } 121 | 122 | public static class AbortPolicy implements RejectedExecutionHandler { 123 | public AbortPolicy() { } 124 | public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 125 | throw new RejectedExecutionException("Task " + r.toString() + 126 | " rejected from " + 127 | e.toString()); 128 | } 129 | } 130 | 131 | public static class DiscardPolicy implements RejectedExecutionHandler { 132 | public DiscardPolicy() { } 133 | public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 134 | } 135 | } 136 | 137 | public static class DiscardOldestPolicy implements RejectedExecutionHandler { 138 | public DiscardOldestPolicy() { } 139 | public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { 140 | if (!e.isShutdown()) { 141 | e.getQueue().poll(); 142 | e.execute(r); 143 | } 144 | } 145 | } 146 | ``` 147 | 148 | - [RejectThreadPoolDemo](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s2/RejectThreadPoolDemo.java) 149 | 150 | #### 3.2.5 自定义线程创建:ThreadFactory 109 151 | 152 | - [MyThreadFactory](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s2/MyThreadFactory.java) 153 | 154 | #### 3.2.6 我的应用我做主:扩展线程池 110 155 | 156 | - 比较了一下ExecuteService中submit和execute函数的区别,通过观察发现,sumit最终也会执行execute函数,具体分析可见这篇[文章](https://www.jianshu.com/p/e05b1d060d7d) 157 | - 顺着execute函数的位置,列一下这几个类的关系,代码如下: 158 | 159 | ```java 160 | //最上层Executor接口 161 | public interface Executor { 162 | void execute(Runnable command); 163 | } 164 | 165 | //继承了Executor接口的ExecutorService接口 166 | public interface ExecutorService extends Executor { 167 | //中间各种函数,但不包含execute函数 168 | } 169 | 170 | //实现了ExecutorService接口的AbstractExecutorService抽象类 171 | public abstract class AbstractExecutorService implements ExecutorService { 172 | //省略其他函数... 173 | 174 | //submit函数内调用了execute,但该抽象类没有execute函数的具体实现 175 | public Future submit(Runnable task) { 176 | if (task == null) throw new NullPointerException(); 177 | RunnableFuture ftask = newTaskFor(task, null); 178 | execute(ftask);//调用了Executor的execute方法 179 | return ftask; 180 | } 181 | } 182 | 183 | //实现了AbstractExecutorService抽象类的ThreadPoolExecutor类 184 | public class ThreadPoolExecutor extends AbstractExecutorService { 185 | //省略其他函数... 186 | 187 | //execute函数的具体实现 188 | public void execute(Runnable command) { 189 | if (command == null) 190 | throw new NullPointerException(); 191 | int c = ctl.get(); 192 | if (workerCountOf(c) < corePoolSize) { 193 | if (addWorker(command, true)) 194 | return; 195 | c = ctl.get(); 196 | } 197 | if (isRunning(c) && workQueue.offer(command)) { 198 | int recheck = ctl.get(); 199 | if (! isRunning(recheck) && remove(command)) 200 | reject(command); 201 | else if (workerCountOf(recheck) == 0) 202 | addWorker(null, false); 203 | } 204 | else if (!addWorker(command, false)) 205 | reject(command); 206 | } 207 | } 208 | ``` 209 | 210 | - [ExtThreadPool](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s2/ExtThreadPool.java) 211 | 212 | 213 | #### 3.2.7 合理的选择:优化线程池线程数量 112 214 | 215 | 请见书中公式 216 | 217 | #### 3.2.8 堆栈去哪里了:在线程池中寻找堆栈 113 218 | 219 | - 程序的本质意思就是写一个类重写execute和submit方法,加一个包装,让该包装可以抛出异常信息 220 | - [TraceThreadPoolExecutor](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s2/TraceThreadPoolExecutor.java) 221 | 222 | #### 3.2.9 分而治之:Fork/Join框架 117 223 | 224 | - 本质就是一种递归的调用,然后不断缩小规模直到可以计算,最后将结果加起来 225 | - [CountTask](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s2/CountTask.java) 226 | 227 | ### 3.3 不要重复发明轮子:JDK的并发容器 121 228 | 229 | - 本节代码都是`java.util.concurrent;`包中的源代码,故而不修改每个文件的包引入行,保持代码原有的样子,方便读者观看 230 | 231 | #### 3.3.1 超好用的工具类:并发集合简介 121 232 | 233 | 注:此处使用[JDK1.7](https://github.com/guanpengchn/JDK/tree/master/JDK1.7)的源代码 234 | 235 | - [ConcurrentHashMap](https://github.com/guanpengchn/JDK/blob/master/JDK1.7/src/java/util/concurrent/ConcurrentHashMap.java),线程安全的HahsMap 236 | - [CopyOnWriteArrayList](https://github.com/guanpengchn/JDK/blob/master/JDK1.7/src/java/util/concurrent/CopyOnWriteArrayList.java),线程安全的ArrayList一族 237 | - [ConcurrentLinkedQueue](https://github.com/guanpengchn/JDK/blob/master/JDK1.7/src/java/util/concurrent/ConcurrentLinkedQueue.java),线程安全的LinkedList 238 | - [BlockingQueue](https://github.com/guanpengchn/JDK/blob/master/JDK1.7/src/java/util/concurrent/BlockingQueue.java),阻塞队列 239 | - [ConcurrentSkipListMap](https://github.com/guanpengchn/JDK/blob/master/JDK1.7/src/java/util/concurrent/ConcurrentSkipListMap.java),跳表,用于快速查找 240 | 241 | #### 3.3.2 线程安全的HashMap 122 242 | 243 | - 将HashMap变为线程安全的,可用以下方法,但并发级别不高 244 | 245 | ```java 246 | public static Map m=Collections.synchronizedMap(new HashMap()); 247 | ``` 248 | 249 | - 更加专业的并发HashMao是ConcurrentHashMap 250 | 251 | #### 3.3.3 有关List的线程安全 123 252 | 253 | - 将List变为线程安全的,可用以下方法 254 | 255 | ```java 256 | public static List l=Collections.synchronizedList(new LinkedList()); 257 | ``` 258 | 259 | - 更加专业的并发HashMap是[ConcurrentHashMap](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s3/ConcurrentHashMap.java) 260 | 261 | #### 3.3.4 高效读写的队列:深度剖析ConcurrentLinkedQueue 123 262 | 263 | - 这里很难,还要再读一遍再做笔记!!!!! 264 | 265 | #### 3.3.5 高效读取:不变模式下的CopyOnWriteArrayList 129 266 | 267 | - 读读不冲突,读写不冲突,只有写写冲突 268 | - 在写的时候先做一次数据复制,将修改的内容写入副本中,再讲副本替换原来的数据 269 | - [CopyOnWriteArrayList](https://github.com/guanpengchn/java-concurrent-programming/blob/master/src/main/java/ch3/s3/CopyOnWriteArrayList.java) 270 | 271 | #### 3.3.6 数据共享通道:BlockingQueue 130 272 | #### 3.3.7 随机数据结构:跳表(SkipList) 134 273 | 274 | ### 3.4 参考资料 136 --------------------------------------------------------------------------------