Java的并发是在顺序语言的基础上提供对线程的支持的。
并发能够更加有效的执行我们的代码,也就是更加合理的应用CPU资源。
并发程序往往CPU和内存使用率,要高于同等的非并发程序。
下面就用Think_in_java_4th,并发这个章节中源码简单说一下自己的认识。
LiftOff.java
package concurrency; //: concurrency/LiftOff.java // Demonstration of the Runnable interface. public class LiftOff implements Runnable { protected int countDown = 10; // Default private static int taskCount = 0; private final int id = taskCount++; public LiftOff() { } public LiftOff(int countDown) { this.countDown = countDown; } public String status() { return "#" + id + "(" + (countDown > 0 ? countDown : "Liftoff!") + "), "; } public void run() { while (countDown-- > 0) { System.out.print(status()); //线程调度器 //将CPU从一个线程转移給另一个线程。 Thread.yield(); } } } /// :~
MainThread.java
package concurrency; //: concurrency/MainThread.java public class MainThread { public static void main(String[] args) { LiftOff launch = new LiftOff(); launch.run(); } } /* * Output: #0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), * #0(Liftoff!), */// :~
MainThread的执行结果和我们不使用多线程基本上没有什么区别。
package concurrency; //: concurrency/BasicThreads.java // The most basic use of the Thread class. public class BasicThreads { public static void main(String[] args) { Thread t = new Thread(new LiftOff()); t.start(); System.out.println("Waiting for LiftOff"); } } /* * Output: (90% match) Waiting for LiftOff #0(9), #0(8), #0(7), #0(6), #0(5), * #0(4), #0(3), #0(2), #0(1), #0(Liftoff!), */// :~
Thread 类使用后,我们可以看到。【"Waiting for LiftOff"】比【#0(9),...ff!),】更早被打印出来了。
此时,CPU和内存的使用情况就初步体现出来了。
new Thread的JDK源码。
target(实现了Runnable的类)最终被给了一个新的tid(nextThreadID)之后,加入到ThreadGroup中。
Thread
public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) { 。。。。。。
g.addUnstarted();
。。。。。。 this.target = target; setPriority(priority); if (parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ tid = nextThreadID(); }
好了,我们大概知道new Thread 的过程了。此处应该有图,哈哈。偷个懒。
也就是说,在【new Thread(new LiftOff())】被给予新的tid并加入到ThreadGroup的时候,System.out执行了。
并且,System.out没有等待【t.start();】的执行完,再开始执行。
这样的结果就是因为,主线程和子线程并发执行的结果。
这时,【在顺序语言的基础上提供对线程的支持】句话就可以拿出来再理解一下了。
Thread
public synchronized void start() { ...... /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ group.add(this); ...... }
ThreadGroup
void add(Thread t) { ...... nUnstartedThreads--; ...... }
MoreBasicThreads.java
package concurrency; //: concurrency/MoreBasicThreads.java // Adding more threads. public class MoreBasicThreads { public static void main(String[] args) { for (int i = 0; i < 5; i++) new Thread(new LiftOff()).start(); System.out.println("Waiting for LiftOff"); } } /* * Output: (Sample) Waiting for LiftOff #0(9), #1(9), #2(9), #3(9), #4(9), * #0(8), #1(8), #2(8), #3(8), #4(8), #0(7), #1(7), #2(7), #3(7), #4(7), #0(6), * #1(6), #2(6), #3(6), #4(6), #0(5), #1(5), #2(5), #3(5), #4(5), #0(4), #1(4), * #2(4), #3(4), #4(4), #0(3), #1(3), #2(3), #3(3), #4(3), #0(2), #1(2), #2(2), * #3(2), #4(2), #0(1), #1(1), #2(1), #3(1), #4(1), #0(Liftoff!), #1(Liftoff!), * #2(Liftoff!), #3(Liftoff!), #4(Liftoff!), */// :~
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #1(9), #2(9), #1(8), #0(2), #3(9), #1(7), Waiting for LiftOff #3(8), #3(7), #3(6), #3(5), #3(4), #3(3), #3(2), #3(1), #3(Liftoff!), #1(6), #1(5), #1(4), #1(3), #1(2), #1(1), #1(Liftoff!), #2(8), #2(7), #2(6), #2(5), #2(4), #2(3), #2(2), #2(1), #2(Liftoff!), #0(1), #4(9), #0(Liftoff!), #4(8), #4(7), #4(6), #4(5), #4(4), #4(3), #4(2), #4(1), #4(Liftoff!),
创建多个线程,并启动。
实际上,线程的创建销毁是非常快的。当一个线程完成了它的任务的时候,该线程占有的资源就会被释放。
那么我们就又可以把已经释放的资源用于创建其他新的线程了。
参考
Java编程思想(第4版) 654页开始
Thinking in Java(第四版 ) 1116页开始