并发操作
并发操作之——多线程
并发操作之——多线程
前言
并发操作之——多线程。
一、实现多线程有几种方式?
1、继承Thread类
示例代码:
/**
* @author Cym
* @date 2021/8/30
*/
public class Thread extends java.lang.Thread {
@Override
public void run() {
System.out.println(java.lang.Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread thread = new Thread();
thread.setName("Robert");
thread.start();
System.out.println(Thread.currentThread().getName());
}
}
继承Thread,重写里面run方法,创建实例,执行start
优点:
代码编写最简单直接操作
缺点:
没返回值,继承一个类后,没法继承其他的类,拓展性差
2、实现Runnabel接口
示例代码:
1、通过实现类完成
package thread;
/**
* @author Cym
* @date 2021/8/30
*/
public class Thread2 implements Runnable{
@Override
public void run() {
System.out.println("通过Runnable实现多线程,名称:"+Thread.currentThread().getName());
}
}
package thread;
/**
* @author Cym
* @date 2021/8/30
*/
public class Thread1 {
public static void main(String[] args) {
Thread2 thread2 = new Thread2();
Thread thread = new Thread(thread2);
thread.setName("Robert");
thread.start();
System.out.println("主线程名称:"+Thread.currentThread().getName());
}
}
2、JDK8之后通过lambda表达式完成
package thread;
/**
* @author Cym
* @date 2021/8/30
*/
public class Thread1 {
public static void main(String[] args) {
Thread thread = new Thread(()->{
System.out.println("通过Runnable实现多线程,名称:"+Thread.currentThread().getName());
});
thread.setName("Robert");
thread.start();
System.out.println("主线程名称:"+Thread.currentThread().getName());
}
}
二、
1、通过Callable和FutureTask方式
创建callable接口的实现类,并实现call方法,结合FutureTask类包装Callable对象,实现多线程
优点:
有返回值,拓展性也高
缺点:
jdk5以后才支持,需要重写call方法,结合多个类比如FutureTask和Thread类
代码如下(示例):
MyTask
package thread;
import java.util.concurrent.Callable;
/**
* @author Cym
* @date 2021/8/30
*/
public class MyTask implements Callable<Object> {
@Override
public Object call() throws Exception {
System.out.println("通过Callable实现多线程,名称:"+Thread.currentThread().getName());
return "这是返回值";
}
}
Thread
package thread;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* @author Cym
* @date 2021/8/30
*/
public class Thread1 {
public static void main(String[] args) {
// MyTask myTask = new MyTask();
FutureTask<Object> futureTask = new FutureTask<>(()->{
System.out.println("通过Callable实现多线程,名称:"+Thread.currentThread().getName());
return "这是返回值";
});
Thread thread = new Thread(futureTask);
thread.setName("Robert");
thread.start();
System.out.println("主线程名称:"+Thread.currentThread().getName());
try {
System.out.println(futureTask.get());
} catch (InterruptedException e) {
//阻塞等待中被中断,则抛出
e.printStackTrace();
} catch (ExecutionException e) {
//执行过程发送异常被抛出
e.printStackTrace();
}
}
}
2、通过线程池创建
自定义Runnable接口,实现run方法,创建线程池,调用执行方法并传入对象
优点:
安全高性能,复用线程
缺点:
jdk5后才支持,需要结合Runnable进行使用
代码如下(示例):
package thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author Cym
* @date 2021/8/30
*/
public class Thread1 implements Runnable {
@Override
public void run() {
System.out.println("通过线程池+runnable实现多线程,名称:" + Thread.currentThread().getName());
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
executorService.execute(new Thread1());
}
System.out.println("主线程名称:" + Thread.currentThread().getName());
//关闭线程池
executorService.shutdown();
}
}
该处使用的url网络请求的数据。
总结
一般常用的Runnable 和 第四种线程池+Runnable,简单方便扩展,和高性能 (池化的思想)。