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多线程(二)--线程池