package com.yuan.test; 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()); Thread.yield(); } } public static void main(String[] args){ LiftOff lo=new LiftOff(); lo.status(); lo.run(); LiftOff lo1=new LiftOff(); lo1.status(); lo1.run(); } } ///:~
每個須要並行處理的任務都須要實現Runable接口。java
The identifier id distinguishes between multiple instances of the task. It is final because it is
not expected to change once it is initialized.apache
上述ID 是用來區分線程的個數的,並且由於它是final 類型的因此一旦實例化了就不會被修改了。
A task’s run( ) method usually has some kind of loop that continues until the task is no
longer necessary, so you must establish the condition on which to break out of this loop (one
option is to simply return from run( )). app
Often, run( ) is cast in the form of an infinite loop,which means that, barring some factor that causes run( ) to terminate, it will continue forever (later in the chapter you’ll see how to safely terminate tasks).
ide
The call to the static method Thread.yield( ) inside run( ) is a suggestion to the thread
scheduler (the part of the Java threading mechanism that moves the CPU from one thread to
the next) that says,oop
一、Thread.yields()ui
Thread.yields()是一個靜態的方法,用來給CPU提一下建議說,「您已經幫我完成最重要的工做了,你要是忙,你就先走吧」this
"I’ve done the important parts of my cycle and this would be a good time
to switch to another task for a while."spa
It’s completely optional, but it is used here because it tends to produce more interesting output in these examples: You’re more likely to see evidence of tasks being swapped in and out.
線程
public class TestThread { public static void main(String[] args) { Thread t = new Thread(new LiftOff()); t.start(); System.out.println("Waiting for LiftOff1"); Thread t1 = new Thread(new LiftOff()); t1.start(); System.out.println("Waiting for LiftOff2"); } }
經過將實現了Runable接口的任務做爲參數來實例化線程。rest
output:
Waiting for LiftOff1
Waiting for LiftOff2
#1(9), #0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!), #1(8), #1(7), #1(6), #1(5), #1(4), #1(3), #1(2), #1(1), #1(Liftoff!),
經過觀察輸出結果能夠看出,兩個線程是隨機執行的。
When main( ) creates the Thread objects, it isn’t capturing the references for any of them.
With an ordinary object, this would make it fair game for garbage collection, but not with a
Thread. Each Thread "registers" itself so there is actually a reference to it someplace, and
the garbage collector can’t clean it up until the task exits its run( ) and dies. You can see
from the output that the tasks are indeed running to conclusion, so a thread creates a
separate thread of execution that persists after the call to start( ) completes.
下面還有一種使用並行處理線程的方法:經過引入ExecutorService和Executors 來並行處理線程。其中
ExecutorService 是經過Executors的靜態方法來實例化的。
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.log4j.lf5.LF5Appender; public class TestThread { public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); // Constructor argument is number of threads:能夠固定初始化線程的數//目 ExecutorService exec = Executors.newFixedThreadPool(5); for(int i = 0; i < 5; i++) exec.execute(new LiftOff()); exec.shutdown(); } }
二、關於CachedThreadPools和FixedThreadPools的一點說明。
Note that in any of the thread pools, existing threads are automatically reused when possible.
線程池裏面的線程都是能夠再利用的。
Although this book will use CachedThreadPools, consider using FixedThreadPools in
production code.
A CachedThreadPool will generally create as many threads as it needs
during the execution of a program and then will stop creating new threads as it recycles the
old ones, so it’s a reasonable first choice as an Executor.
CachedThreadPool將會持續不斷生成threads,直到有能夠再利用的線程,因此這種方法彷佛是比較合理的。
Only if this approach causes
problems do you need to switch to a FixedThreadPool.
若是你發現CatchedThreadPool會產生問題,那麼你要想一想用FixedThreadPool.
三、newSingleThreadExecutor
public class TestThread { public static void main(String[] args) { ExecutorService exec = Executors.newSingleThreadExecutor(); for(int i = 0; i < 5; i++) exec.execute(new LiftOff()); exec.shutdown(); } }
說明:值實例化了一個線程,若是還有其它的任務,這些任務就進入了隊列。等待被執行,從輸出的結果來看,是按照順序執行的。
output:
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(Liftoff!), #1(9), #1(8), #1(7), #1(6), #1(5), #1(4), #1(3), #1(2), #1(1), #1(Liftoff!), #2(9), #2(8), #2(7), #2(6), #2(5), #2(4), #2(3), #2(2), #2(1), #2(Liftoff!), #3(9), #3(8), #3(7), #3(6), #3(5), #3(4), #3(3), #3(2), #3(1), #3(Liftoff!), #4(9), #4(8), #4(7), #4(6), #4(5), #4(4), #4(3), #4(2), #4(1), #4(Liftoff!),