java多线程实现表复制_Java多线程的三种实现方式
今天簡單說一下Java三種多線程實現方式和區別,主要有實現Runnable、Callable和繼承Thread三種方式。
實現Runnable的方式
這種方式比較常用,當我們的線程類有繼承其他的類的情況下(Java不支持類多繼承),并且線程任務不需要返回值的情況下可以選用這種方式。
public class ThreadRunnableDemo implementsRunnable{
/**計數變量*/
private int count = 0;
public static void main(String[] args) throwsInterruptedException {
ThreadRunnableDemo threadRunnableDemo = newThreadRunnableDemo();
//實例化線程
Thread thread = new Thread(threadRunnableDemo, "threadRunnableDemoA"); System.out.println(String.format("線程狀態preStart: %s", thread.getState()));
//啟動線程
thread.start(); System.out.println(String.format("線程狀態afterStart: %s", thread.getState()));
//主線程休眠1000ms
Thread.sleep(1000); System.out.println(String.format("線程狀態after1000ms: %s", thread.getState()));
}
@Override public voidrun() {
count++;
System.out.println(String.format("線程名稱:%s, 線程狀態:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count));
} }
輸出結果:
線程狀態preStart: NEW 線程狀態afterStart: RUNNABLE 線程名稱:threadRunnableDemoA, 線程狀態:RUNNABLE, count:1
線程狀態after1000ms: TERMINATED
實現Callable的方式
當我們執行線程需要返回值的時候那么就必須選用實現Callable類的方式,因為目前只有這種方式能返回值。當然這種方式我們也可以不需要獲取返回值。
這種方式是通過FutureTask的get()方法(下面代碼的第22行)或者get(long timeout, TimeUnit unit)(下面代碼的第28行)方法獲取返回值。當我們看Callable的接口定義的源碼會發現“public interface Callable?” ,我們實現的時候是需要定義返回類型,如下面代碼所示。
除此之外我們還需要注意的是:當我們通過FutureTask的get()方法去獲取線程的返回值的時候是要等到線程call()內容都執行完畢之后才能獲取得到,并且get()方法后面的代碼必須等待,說明這一定是同步的,所以我們可以在真正需要線程返回值的時候才通過get()方法去獲取,以免被阻塞。當我們通過get(long timeout, TimeUnit unit)方式去獲取的時候可以設置超時時間,如果超過所設置的超時時間都沒有獲取到線程返回的值則會拋出 java.util.concurrent.TimeoutException 異常,當然如果在get(long timeout, TimeUnit unit)之前用get()方式獲取了的話就不會拋異常。
實現Callable還有個好處就是可以線程可以拋異常,如果我們需要在線程里拋出異常的話也可以選用這種方式,其他兩種方式只能捕獲異常信息。
public class ThreadCallableDemo implements Callable{
/**計數變量*/
private int count = 0;
public static void main(String[] args) throwsInterruptedException, ExecutionException, TimeoutException {
ThreadCallableDemo threadCallableDemo = newThreadCallableDemo();
//通過FutureTask獲取返回值
FutureTask taskA = new FutureTask<>(threadCallableDemo);
//實例化線程
Thread thread = new Thread(taskA, "threadCallableDemoA"); System.out.println(String.format("線程狀態preStart: %s", thread.getState()));
//啟動線程
thread.start(); System.out.println(String.format("線程狀態afterStart: %s", thread.getState()));
//通過FutureTask的get()方法獲取返回值
int result =taskA.get(); System.out.println("是否同步測試...."); System.out.println(String.format("result: %s", result)); System.out.println(String.format("線程狀態afterGetResult1: %s", thread.getState()));
//通過FutureTask的get()方法獲取返回值 設置超時時間 單位為ms
int resultWithTime = taskA.get(100, TimeUnit.MILLISECONDS); System.out.println(String.format("resultWithTime: %s", resultWithTime)); System.out.println(String.format("線程狀態afterGetResult2: %s", thread.getState()));
}
/**
* 實現Callable的call類 */
@Override public Integer call() throwsException {
//自增
count++;
System.out.println(String.format("線程名稱:%s, 線程狀態:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count)); System.out.println("休眠1000ms...."); Thread.currentThread().sleep(1000);
returncount; } }
輸出結果:
線程狀態preStart: NEW 線程狀態afterStart: RUNNABLE 線程名稱:threadCallableDemoA, 線程狀態:RUNNABLE, count:1
休眠1000ms.... 是否同步測試.... result: 1
線程狀態afterGetResult1: TERMINATED resultWithTime: 1
線程狀態afterGetResult2: TERMINATED
繼承Thread的方式
Thread類實際上也是實現Runnable接口,所以當我們繼承Thread的時候我們即使不實現run()方法也不會報錯,這種方式也經常用。
下面我寫了兩種不同繼承Thread的代碼,大家可以看一下區別,我在網上看到很多人說 繼承Thread實現多線程,線程間不能共享數據,但是我用下面的代碼1方式似乎也可以共享哇,歡迎大家提出質疑。
代碼1:
public class ThreadThreadDemo extendsThread{
/**計數變量*/
private int count = 0;
public static void main(String[] args) throwsInterruptedException {
ThreadThreadDemo threadThreadDemo = newThreadThreadDemo();
//實例化線程
Thread thread = new Thread(threadThreadDemo, "threadThreadDemoA"); System.out.println(String.format("線程狀態preStart: %s", thread.getState()));
//啟動線程
thread.start(); System.out.println(String.format("線程狀態afterStart: %s", thread.getState()));
//主線程休眠1000s
Thread.sleep(1000); System.out.println(String.format("線程狀態after1000ms: %s", thread.getState())); }
@Override public voidrun() {
count++;
System.out.println(String.format("線程名稱:%s, 線程狀態:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count)); } }
輸出結果1:
線程狀態preStart: NEW 線程狀態afterStart: RUNNABLE 線程名稱:threadThreadDemoA, 線程狀態:RUNNABLE, count:1
線程狀態after1000ms: TERMINATED
代碼2:
public class ThreadThreadDemo extendsThread{
/**計數變量*/
private int count = 0;
public static void main(String[] args) throwsInterruptedException {
ThreadThreadDemo threadThreadDemo = newThreadThreadDemo();
//實例化線程
System.out.println(String.format("線程狀態preStart: %s", threadThreadDemo.getState()));
//啟動線程
threadThreadDemo.start(); System.out.println(String.format("線程狀態afterStart: %s", threadThreadDemo.getState()));
//主線程休眠1000s
Thread.sleep(1000); System.out.println(String.format("線程狀態after1000ms: %s", threadThreadDemo.getState())); }
@Override public voidrun() {
count++;
System.out.println(String.format("線程名稱:%s, 線程狀態:%s, count:%s", Thread.currentThread().getName(), Thread.currentThread().getState(), count)); } }
輸出結果2:
線程狀態preStart: NEW 線程狀態afterStart: RUNNABLE 線程名稱:Thread-0, 線程狀態:RUNNABLE, count:1
線程狀態after1000ms: TERMINATED
最后總結:
如果不要求線程返回結果,也不需要拋異常也沒有繼承其他的類,那么三種方式可以任選,看喜好;
如果有繼承其他類,那么就只能用實現Runnable和實現Callable的方式;
如果需要線程返回結果或者需要線程拋異常那么選擇實現Callable的方式的方式,但是需要注意的是獲取返回結果是同步的方式。
如果有疑問或者有問題歡迎留言討論!
總結
以上是生活随笔為你收集整理的java多线程实现表复制_Java多线程的三种实现方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python数字列表in_Python入
- 下一篇: java美元兑换,(Java实现) 美元