其實建立線程遠遠不止有3種方式,但這裏只記錄三種。html
一、經過繼承Thread類來建立一個線程:
步驟1:定義一個繼承Thread類的子類:
步驟2:構造子類的一個對象: Thread t1 = new Thread();
步驟3:啓動線程: t1.start();
至此,一個線程就建立完成了。 java
二、經過實現Runnable接口來建立Thread線程:
步驟1:建立實現Runnable接口的類:
步驟2:建立一個類對象: Runnable runnable = new SomeRunnable();
步驟3:由Runnable建立一個Thread對象: Thread t2 = new Thread(runnable);
步驟4:啓動線程: t2.start();
至此,一個線程就建立完成了。
三、與方法2相似,經過實現Callable接口來建立Thread線程。
步驟1:建立實現Callable接口的類;
步驟2:建立一個類對象: Callable callable = new SomeCallable();
步驟3:由Callable建立一個FutureTask對象: FutureTask ft= new FutureTask(callable);
步驟4:由FutureTask建立一個Thread對象: Thread oneThread = new Thread(ft);
步驟5:啓動線程: oneThread.start();
至此,一個線程就建立完成了。 dom
可參考:推薦:http://www.importnew.com/25286.htmlide
package resource.java.ordinary.mul.thread; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * 線程Demo * * @author xiao */ public class TranditionThread { public static void main(String[] args) throws InterruptedException, ExecutionException { /* * 建立線程的方法一: */ Thread thread = new Thread() { @Override public void run() { // excuMethod(1); } }; thread.start(); /* * 建立線程方法二: */ Thread thread2 = new Thread(new Runnable() { @Override public void run() { // excuMethod(2); } }); thread2.start(); /* * 建立線程方法三: */ // FutureTask是一個包裝器,它經過接受Callable來建立,它同時實現了 Future和Runnable接口。 FutureTask<String> ft = new FutureTask<String>(new Callable<String>() { @Override public String call() throws Exception { // excuMethod(3); System.out.println("hi~~ 此處有個新線程"); return "FutureTask 返回something"; } }); Thread t3 = new Thread(ft); t3.start(); String result = ft.get(); System.out.println(result);// 輸出: FutureTask 返回something /* * 問題:此方法運行的是excuMethod(4)方法仍是excuMethod(5)方法?? */ new Thread(new Runnable() { @Override public void run() { // excuMethod(4); } }) { @Override public void run() { // excuMethod(5); } }.start(); } private static void excuMethod(int flag) { while (true) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(flag + " " + Thread.currentThread().getName()); } } }
對於上面問題的一個解答:this
答案:運行標識爲5的線程。spa
思路:這個方法的結構是這樣的:線程
new Thread( Runnable.run(){ // 標識爲4的線程 }){ run(){ // 標識爲5的線程 }}.start();
緣由:在Thread.class中,Thread是實現了Runnable接口的。在運行了Thread.start()方法後,先在子類中找run()方法,找到則用子類的方法,找不到在用父類的方法。在這題中,標識爲5的線程所在的run()方法已經重寫了父類的方法,因此最終運行的是excuMethod(5)方法。code
附:Callable與Future的使用實例htm
import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * Callable與Future的使用實例 * @author xiao * */ public class CallableAndFuture { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService threadPool = Executors.newSingleThreadExecutor(); /* * 獲取某一線程的返回結果: * Callbale要採用ExecutorService的submit方提交,返回的future對象能夠取消任務, 也能夠獲取線程的返回結果。 * Future取得的結果類型和Callable返回的結果類型必須一致,這是經過泛型來實現的。 */ Future<String> future = threadPool.submit(new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(2000); return "hello"; // 返回結果 } }); System.out.println("等待出結果"); System.out.println("拿到結果" + future.get());// 獲取結果 /* * 獲取一組線程的返回結果: * CompletionService用於提交一組Callable任務,其take方法放回已經完成的一個Callable任務對應的Future對象。 */ ExecutorService threadPool2 = Executors.newFixedThreadPool(10); CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2); for (int i = 1; i <= 10; i++) { final int seq = i; // 運行每一個線程的任務 completionService.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { Thread.sleep(new Random().nextInt(5000)); return seq; } }); } // 獲得全部線程運行的結果 for (int i = 0; i < 10; i++) { System.out.println(completionService.take().get()); } } }
一、synchronized的四種用法:對象
(1)修飾方法
(2)修飾一個代碼塊
(3)修飾一個靜態方法
(4)修飾一個類
二、synchronized使用的demo
/** * 線程互斥:synchronized * @author xiao * */ public class TranditionThreadSynchronized { public static void main(String[] args) { new TranditionThreadSynchronized().init(); } public void init() { final Output ootput = new Output(); // 第一個線程 new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(1000); ootput.output2("xiao"); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); // 第二個線程 new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(1000); ootput.output2("hag"); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } class Output { public void output(String name) { int len = name.length(); // synchronized(XXX){}中,XXX表示的是要鎖住的對象 // 此this指的是和output2中實現的效果同樣,鎖的是Output對象 synchronized (this) { for (int i = 0; i < len; i++) { System.out.print(name.charAt(i)); } System.out.println(); } } public synchronized void output2(String name) { int len = name.length(); for (int i = 0; i < len; i++) { System.out.print(name.charAt(i)); } System.out.println(); } } }
思考:若是須要在類Output中加入output3()方法(以下代碼塊所示),且output1()和output3()須要保持互斥,則須要作些什麼?
public static synchronized void output3(String name) { int len = name.length(); for (int i = 0; i < len; i++) { System.out.print(name.charAt(i)); } System.out.println(); }
答案:須要作的事情有:
(1)內部類Output須要添加關鍵字static,以此變爲外部類。
(2)將output1()中的synchronized (this)修改成synchronized (Output.class),使output1()方法中鎖定的是Output類。
s