java中创建线程的方式有三种,继承Thread,实现Runable,实现Callable;
继承Threadr
public class TheadTest extends Thread {
@Override
public void run() {
System.out.println("已经启动线程");
}
}
public class Main {
public static void main(String[] args) {
TheadTest theadTest = new TheadTest();
theadTest.start();
System.out.println("主线程");
}
}
输出结果为:
主线程
已经启动线程
可以看到和调用方法是不一样的,如果是调用方法的话,会先执行完方法才会输出“主线程”,这里是异步的,因为输出“已经启动线程”和“主线程”不是在一个线程内,所以会出现“主线程”先被输出的情况;
实现Runable接口
public class TheadTest implements Runnable {
@Override
public void run() {
System.out.println("已经启动线程");
}
}
public class Main {
public static void main(String[] args) {
TheadTest theadTest = new TheadTest();
Thread thread = new Thread(theadTest);
thread.start();
System.out.println("主线程");
}
}
输出结果为:
主线程
已经启动线程
输出结果和上面一样,这里也是启动了新的线程,实现Runable这种方法需要把实现类的实例作为Thread构造函数的参数,创建Thread实例启动线程,
实现Callable接口
这种方法和之前的不同在于这种方法创建的线程是有返回值的
public class TheadTest implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("进入创建的线程");
Thread.sleep(1000);
System.out.println("新线程暂停了1秒钟");
return "线程返回的值";
}
}
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService service = Executors.newSingleThreadExecutor();
TheadTest theadTest = new TheadTest();
Future<String> future;
future = service.submit(theadTest);
System.out.println("做一些其他的事情");
Thread.sleep(1500);
System.out.println("主线程停顿1.5秒后");
String str = future.get();
System.out.println(str);
System.out.println("主线程");
}
}
输出结果为:
做一些其他的事情
进入创建的线程
新线程暂停了1秒钟
主线程停顿1.5秒后
线程返回的值
主线程
这里通过线程池执行了新的线程任务后,主线程可以继续做一些其他的事情,在做完后,可以使用Futured的get方法获得返回值,这个方法是阻塞的,也就是说会一直等待返回值;
如果只是简单的使用线程,使用前两种方法就可以,实现Callable可以抛出call方法的异常,而run是不能抛出异常的;继承Thread和实现Runable效果是一样的,不过因为java的单继承机制,如果继承了Thread就不能再继承其他类,所以一般可以使用实现Runable的方式,因为这样子可以继承其他类,还可以实现多个其他的接口。