JAVA多線程(一)--實現/創建方式
JAVA多線程(一)--實現/創建方式
一、繼承Thread類
Thread類本質上是一個實現了Runnable接口的實例,代表一個線程的實例。啟動線程的唯一方法是調用Thread類的start()方法,start()方法中調用了一個native方法start0(),它將啟動一個線程,并執行run()方法。
//部分Thread源碼
public class Thread implements Runnable {
//......
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* 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);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
// 本地方法,使用c代碼初始化線程,并運行run()方法
private native void start0();
@Override
public void run() {
if (target != null) {
//這里的target是一個Runnable接口實現的引用
target.run();
}
}
// .....
}
代碼:
// 繼承Thread類
public class MyThread extends Thread{
@Override
public void run(){
System.out.println("MyThread running");
}
public static void main(String[] arg){
//創建線程并運行
MyThread myThread = new MyThread();
myThread.start();
}
}
二、實現Runnable接口
如果類已經繼承了一個類,就無法再繼承Thread類,此時可以實現一個Runnable接口。
// Runnable源碼
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
使用Runnable接口實現線程類時,為了啟動線程,需要用該類初始化一個Thread類對象。
// 實現代碼
public class MyThread1 extends MyThread implements Runnable{
@Override
public void run(){
System.out.println("MyThread1 running");
}
public static void main(String[] arg){
MyThread1 myThread1 = new MyThread1();
Thread thread = new Thread(myThread1);
thread.start();
}
}
三、實現Callable接口
無返回值的任務實現Runnable接口,而有返回值的任務就需要實現Callable接口。
執行Callable任務后,返回一個Future對象。在該對象上調用get()方法就可以得到Callable任務返回的對象。使用Callable需要結合ExecutorService線程池接口。
// Callable源碼
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
// 實現代碼:
public class MyCallableThread implements Callable<String> {
private final String name;
MyCallableThread(String name){
this.name = name;
}
@Override
public String call(){
return this.name;
}
public static void main(String[] arg) throws ExecutionException, InterruptedException {
int size = 5;
ExecutorService pool = Executors.newFixedThreadPool(size);
List<Future<String>> futures = new ArrayList<>();
for(int i=0;i<size;i++){
Future<String> future = pool.submit(new MyCallableThread(i+""));
futures.add(future);
}
pool.shutdown();
for (Future<String> future : futures){
System.out.println("res: "+ future.get());
}
}
}
/**
* 執行結果:
* res: 0
* res: 1
* res: 2
* res: 3
* res: 4
*/
四、基于線程池
每次創建線程都要為線程分配堆棧內存以及初始化內存,還需要進行系統調用。頻繁的創建和銷毀線程會大大降低系統運行效率,非常浪費資源??梢允褂镁彺娴牟呗?,也就是線程池來實現多線程。
詳情:JAVA多線程(二)--線程池

浙公網安備 33010602011771號