java并发(一)之四种创建线程的方法
一、继承Thread
1.继承Thread,然后重写它的run()方法。
2.线程唯一的启动方法就是通过Thread的start()方法。**start()是一个native方法,**使用它将执行run()方法。
示例:
public class Thread1 extends Thread{
@Override
public void run() {
System.out.println("继承Thread创建了一个线程");//实质上Thread实现了Runnable
}
public static void main(String[] args){
Thread1 T1 = new Thread1();
T1.start();
}
}
二、实现Runnable
我们可以看到Runnable接口里面只有一个方法run(),它的返回值是void。意味着执行以后不会有返回值。
public interface Runnable {
public abstract void run();
}
使用示例:
public class Thread2 implements Runnable{
@Override
public void run() {
System.out.println("实现了Runnable创建了一个线程");
}
public static void main(String[] args){
Thread thread = new Thread(new Thread2());//需要创建一个Thread实例
thread.start();
}
}
三、实现Callable
我们再来看看Callable接口里面的方法:
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
可以看到Callable的call()方法是有返回值的,返回值就是Callable传入的V,我们一般结合ExecutorService接口的submit方法来使用,submit方法返回的是一个future接口,可以使用get方法来获取里面的值。get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回。
ExecutorService接口的submit方法的几种使用类型,根据需要选择:
使用示例:
public static class Thread3 implements Callable<Object>{
int i=1;
@Override
public Object call() throws Exception {
String str=null;
for(;i<5;i++){
str=Thread.currentThread().getName()+"-----";
System.out.println(str);
}
return str;
}
public static void main(String[] args) throws InterruptedException, ExecutionException{
ExecutorService ES = Executors.newFixedThreadPool(3);//创建一个线程池
List<Future<Object>> list = new ArrayList<Future<Object>>();//用一个list存放返回的future值
for (int i = 1; i < 5; i++) {
Future<Object> f = ES.submit(new Thread3());
list.add(f);
}
ES.shutdown();//关闭线程池
for (Future<Object> f : list) {//输出拿到的future值
System.out.println("res:" + f.get().toString());
}
}
}
结果:
可以看到会一直等线程的任务执行完再输出future的值。
四、使用线程池创建线程
这里推荐个:
https://blog.csdn.net/weixin_41932830/article/details/105266769
总结:这些基本的,最后如果深入学习都不是难事。只是坚持很难。