java多執行緒與併發之建立執行緒的幾種方式
阿新 • • 發佈:2019-02-16
1、繼承Thread類方法
public class Demo1 extends Thread{
@Override
public void run() {
//判斷標誌
while(true) {
System.out.println(getName()+"-->執行緒執行了....");
}
}
public static void main(String[] args) {
Demo1 d1 = new Demo1();
d1.start();
}
}
2、實現Runnable介面
/** * Runnable 作為執行緒任務存在 * @author abel */ public class Demo2 implements Runnable { @Override public void run() { while(true) { System.out.println("執行緒開始執行......"); } } public static void main(String[] args) { Thread t = new Thread(new Demo2()); t.start(); } }
3、採用匿名內部類的方式建立執行緒(使用一次的時候使用)
擴充套件:採用匿名內部類的方式同時採用上面兩種方式會執行子類的run方法public class Demo3 { public static void main(String[] args) { //1)通過thread子類建立匿名內部類 new Thread() { public void run() { System.out.println("執行緒開始執行......"); }; }.start(); //2)通過執行緒任務的方式建立匿名內部類 new Thread(new Runnable() { @Override public void run() { System.out.println("執行緒開始執行......"); } }).start(); } }
結果:public class Demo3 { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { System.out.println("實現runnable介面的run方法......"); } }) { public void run() { System.out.println("執行的子類的run方法......"); }; }.start(); } }
執行的子類的run方法......
原因:因為Thread類在new的時候,雖然傳了Runnable也就是原始碼中的target已經傳到init中了,並且在init中賦給了Thread類的target屬性(此時target指向的是引數中的runnable介面),之後在呼叫start()啟動的時候,就去呼叫了run()方法
public void run() {
if (target != null) {
target.run();
}
}
但子類重寫了run(),所以最後執行的是子類的run()方法,而沒呼叫父類的run()。
4、有返回值的建立方式(實現Callable介面)
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//引數使用泛型,以Integer為例
public class Demo4 implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("正在執行方法體......");
Thread.sleep(3000);
return 100;
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
Demo4 d = new Demo4();
//FutureTask是繼承Runnable,是對Runnable的封裝,所以需要包裝到Thread類中執行
FutureTask<Integer> task = new FutureTask<>(d);
//包裝到Thread類中進行執行
Thread t = new Thread(task);
t.start();
System.out.println("執行別的任務....");
//獲取執行緒執行結果
Integer i = task.get();
System.out.println("執行緒執行結果是:"+i);
}
}
執行結果:
執行別的任務....
正在執行方法體......
執行緒執行結果是:100
5、定時器的方式建立執行緒
public class Demo5 {
public static void main(String[] args) {
Timer timer = new Timer();
//TimerTask是一個抽象類,實現的是runnable介面
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("執行執行緒任務......");
}
}, 0, 1000);
}
}
有很多schedule可選
注意:方法體中出現異常後,該定時任務直接結束
6、使用執行緒池建立執行緒
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo6 {
public static void main(String[] args) {
//建立執行緒池,有多種可選執行緒池
ExecutorService threadPool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
threadPool.execute(new Runnable() { //執行一次
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->執行緒執行......");
}
});
}
//停掉當前執行緒池
threadPool.shutdown();
}
}
執行結果:
pool-1-thread-1-->執行緒執行......
pool-1-thread-5-->執行緒執行......
pool-1-thread-2-->執行緒執行......
pool-1-thread-3-->執行緒執行......
pool-1-thread-6-->執行緒執行......
pool-1-thread-4-->執行緒執行......
pool-1-thread-9-->執行緒執行......
pool-1-thread-7-->執行緒執行......
pool-1-thread-8-->執行緒執行......
pool-1-thread-10-->執行緒執行......
7、採用lambda表示式(函式式)實現
import java.util.Arrays;
import java.util.List;
public class Demo7 {
public int add(List<Integer> values) {
// values.parallelStream().forEach(System.out :: println);
//parallelStream是個並行的
return values.parallelStream().mapToInt(i -> i).sum();
}
public static void main(String[] args) {
List<Integer> values = Arrays.asList(10,20,30,40);
int sum = new Demo7().add(values);
System.out.println("計算結果是:"+sum);
}
}
執行結果:
30
40
10
20
計算結果是:100