在Java中创建线程有以下三种方式
- 继承Thread
- 实现Runnable接口
- 通过 Callable 和 Future 创建线程
一、继承Thread创建线程
public class Thread1 extends Thread{
@Override
public void run() {
}
public static void main(String[] args) {
//启动线程
new Thread.start();
}
}
二、实现Runnable接口
public class Thread1 implements Runnable{
@Override
public void run() {
}
public static void main(String[] args) {
//启动线程
new Thread(new Thread1()).start();
}
}
三. 通过 Callable 和 Future 创建线程
public class CallableThreadTest implements Callable<Integer> {
@Override
public Integer call() throws Exception
{
}
}
以上就是线程创建的三种方式 (一般使用实现Runnable接口方式创建线程)
四.3种方式创建线程方式对比
- 继承Thread与实现Runnable接口
先看看Thread的结构
从Thread结构上看Thread也是通过继承Runnable创建的线程,他们之间是多态关系
使用Thread创建线程最大的局限性就是只能单继承不能多继承,而使用实现Runnable接口方式创建线程这这种局限性则不存在,可以一边实现一边继承,但是他们的工作性质是相同的 - Runnable和Callable的区别
(1) Callable规定(重写)的方法是call(),Runnable规定(重写)的方法是run()。
(2) Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
(3) call方法可以抛出异常,run方法不可以。
(4) 运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果。
五、使用多线程注意事项
1. 使用多线程,代码的运行结果与执行顺序或调用顺序无关
例:
public class ThreadTest extends Thread{
@Override
public void run() {
System.out.println("ThreadTest");
}
public static void main(String[] args)
{
new ThreadTest().start();
System.out.println("运行结束");
}
}
运行结果
2. 执行start不代表线程的启动顺序
public class ThreadTest extends Thread {
int id;
ThreadTest(int id) {
this.id = id;
}
@Override
public void run() {
System.out.println("ThreadTest id=" + id);
}
public static void main(String[] args) {
new ThreadTest(1).start();
new ThreadTest(2).start();
new ThreadTest(3).start();
new ThreadTest(4).start();
new ThreadTest(5).start();
}
}
运行结果
3. 直接调用run方法不会启动线程此时run方法和一般方法一样
在Thread类中使用start()方法“通知线程规划器” 线程准备就绪,等待调用线程的run方法,这个过程就是让系统安排一个时间调用Thread中的run()方法,也就是运行线程,启动线程具有异步性,如果直接调用thread.run()就不是异步执行,而是同步,那么此线程对象不是交给“线程管理器”,而是交给main主线程调用,即main线程执行run方法
例:
public class ThreadTest extends Thread {
int id;
ThreadTest(int id) {
this.id = id;
}
@Override
public void run() {
//Thread.currentThread()获取当前线程对象
//getName()获取线程名称
System.out.println("ThreadName"+id+":"+Thread.currentThread().getName());
}
public static void main(String[] args) {
new ThreadTest(1).start();
new ThreadTest(2).run();
}
}
运行结果
由以上结果可知 id为1的run是由Thread-0线程调用
而id=2的run是由main主线程调用
———————————————————————————————————
作者新手一枚,如有错漏,还望指正