创建线程主要有以下几种方式:
1. 继承Thread类
创建一个新的类继承自Thread
类,并重写其run
方法。然后创建该类的实例并调用start
方法来启动线程。
class MyThread extends Thread {
public void run() {
// 线程执行的操作
}
}
MyThread thread = new MyThread();
thread.start();
2. 实现Runnable接口
创建一个新的类实现Runnable
接口,并实现其run
方法。然后创建该类的实例,并将其作为参数传递给Thread
类的构造函数,再调用Thread
实例的start
方法。
class MyRunnable implements Runnable {
public void run() {
// 线程执行的操作
}
}
Thread thread = new Thread(new MyRunnable());
thread.start();
3. 实现Callable接口
创建一个新的类实现Callable
接口,并实现其call
方法。与Runnable
不同的是,Callable
允许任务完成后返回值。将Callable
实例提交给ExecutorService
,并获取Future
对象,通过这个对象可以检查任务是否完成,并获取返回值。
class MyCallable implements Callable<Integer> {
public Integer call() {
// 线程执行的操作,并返回结果
return 123;
}
}
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(new MyCallable());
// 可以用future.get()获取结果
4. 使用Executor框架
Java的java.util.concurrent
包提供了Executor
框架,可以更简单和强大地管理线程生命周期。Executors
类提供了工厂方法来创建线程池。
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.execute(new MyRunnable());
executor.shutdown();
线程的生命周期
线程在其生命周期中可能会处于以下几种状态:
- 新建(New):新创建了一个线程对象,但还没有调用它的
start()
方法。 - 可运行(Runnable):调用
start()
方法后,线程处于可运行状态。此时,线程可能正在运行或者准备运行,取决于操作系统给线程提供运行的机会。 - 阻塞(Blocked):线程因为等待监视器锁(synchronized block)而被阻塞。
- 等待(Waiting):线程等待其他线程通知或中断,例如调用了
Object.wait()
、Thread.join()
或LockSupport.park()
。 - 超时等待(Timed Waiting):类似于等待状态,但有时间限制,例如
Thread.sleep()
、Object.wait(long timeout)
、Thread.join(long millis)
。 - 终止(Terminated):线程的
run()
方法执行完毕或者因为异常退出了run()
方法,线程结束其生命周期。
线程在其生命周期中可能会因为调用特定的方法或者发生特定事件而从一种状态转变到另一种状态。理解线程的生命周期对于编写正确的多线程程序非常重要。