java 多线程入门
1.多线程是什么?
按本人的理解,多线程就是让你的代码同时(并行)执行,缩短代码的运行时间。
2.举个例子
有个业务需求,需要发送邮件和发送短信。发送邮件和发送短信的方法模拟如下:
import java.util.Random;
/**
* 发邮件类
*/
public class EmailUtil {
/**
* 发邮件
* @param message 消息
* @return 如果成功返回true,失败返回false
*/
public static boolean sendEmail(String message){
try {
Thread.sleep(4000); //模拟发邮件需要3秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("正在发送邮件,内容为:"+message);
int res = new Random().nextInt(2); //随机产生0(成功)和1(失败)
if(res==0){
System.out.println("发送邮件成功");
return true;
}else{
System.out.println("发送邮件失败");
return false;
}
}
}
import java.util.Random;
/**
* 发短信类
*/
public class PhoneUtil {
/**
* 发短信
* @param message 消息
* @return 如果成功返回true,失败返回false
*/
public static boolean sendPhoneMessage(String message){
try {
Thread.sleep(4000); //模拟发邮件需要3秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("正在发送短信,内容为:"+message);
int res = new Random().nextInt(2); //随机产生0(成功)和1(失败)
if(res==0){
System.out.println("发送短信成功");
return true;
}else{
System.out.println("发送短信失败");
return false;
}
}
}
2.1 串行发送邮件,发送短信
程序的模拟业务如下:
public class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
String message = "boss,I want more money!!!";
sendMessage(message);
long endTime = System.currentTimeMillis();
System.out.println("发送消息结束!!!耗时:"+(endTime-startTime)+"毫秒");
}
/**
* 串行调用发邮件,发短信
* @param message 消息
*/
public static void sendMessage(String message){
EmailUtil.sendEmail(message);
PhoneUtil.sendPhoneMessage(message);
}
}
串行调用先发邮件后发短信 。由于发短信和发邮件代码模拟都是耗时4000毫秒。因此,程序的总耗时应该是8000毫秒以上,我们来看下运行结果:
正在发送邮件,内容为:boss,I want more money!!!
发送邮件失败
正在发送短信,内容为:boss,I want more money!!!
发送短信成功
发送消息结束!!!耗时:8016毫秒
2.2 并行发送邮件,发送短信
如果我们利用多线程,发邮件和发短信同时进行,代码应该怎么写呢?(道友们可以百度下java线程应该怎么写,下面我直接贴出代码)
public class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
String message = "boss,I want more money!!!";
// sendMessage(message);
sendMessageWithThread(message);
long endTime = System.currentTimeMillis();
System.out.println("发送消息结束!!!耗时:"+(endTime-startTime)+"毫秒");
}
/**
* 串行调用发邮件,发短信
* @param message 消息
*/
public static void sendMessage(String message){
EmailUtil.sendEmail(message);
PhoneUtil.sendPhoneMessage(message);
}
/**
* 多线程并行调用发邮件,发短信
* @param message
*/
public static void sendMessageWithThread(String message){
Thread t1 = new Thread(()->EmailUtil.sendEmail(message));
Thread t2 = new Thread(()->PhoneUtil.sendPhoneMessage(message));
t1.start();
t2.start();
try {
t1.join(); //让t1线程执行完,再往下执行main方法
t2.join(); //让t2线程执行完,再往下执行main方法
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
下面我们再来看多线程并行的运行结果
正在发送邮件,内容为:boss,I want more money!!!
正在发送短信,内容为:boss,I want more money!!!
发送邮件失败
发送短信成功
发送消息结束!!!耗时:4041毫秒
2.3 并行发送邮件,发送短信,并返回结果
细心的道友们发现,发送邮件和发送短信的调用是有可能失败的。但是上面的多线程没有返回结果。如果我们需要返回结果,程序该怎么写呢?(先思考一下,代码如下)
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
String message = "boss,I want more money!!!";
// sendMessage(message);
// sendMessageWithThread(message);
sendMessageWithCallBack(message);
long endTime = System.currentTimeMillis();
System.out.println("发送消息结束!!!耗时:"+(endTime-startTime)+"毫秒");
}
/**
* 串行调用发邮件,发短信
* @param message 消息
*/
public static void sendMessage(String message){
EmailUtil.sendEmail(message);
PhoneUtil.sendPhoneMessage(message);
}
/**
* 多线程并行调用发邮件,发短信
* @param message 消息
*/
public static void sendMessageWithThread(String message){
Thread t1 = new Thread(()->EmailUtil.sendEmail(message));
Thread t2 = new Thread(()->PhoneUtil.sendPhoneMessage(message));
t1.start();
t2.start();
try {
t1.join(); //让t1线程执行完,再往下执行main方法
t2.join(); //让t2线程执行完,再往下执行main方法
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 多线程并行调用发邮件,发短信
* @param message 消息
* @return 返回发送邮件和发送短信的结果
*/
public static List<Boolean> sendMessageWithCallBack(String message){
ExecutorService executorService = Executors.newCachedThreadPool();
Callable<Boolean> callable1 = ()->EmailUtil.sendEmail(message);
Callable<Boolean> callable2 = ()->PhoneUtil.sendPhoneMessage(message);
Future<Boolean> future1 = executorService.submit(callable1);
Future<Boolean> future2 = executorService.submit(callable2);
List<Boolean> res = new ArrayList<>();
try {
res.add(future1.get());
res.add(future2.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
System.out.println("发送邮件,是否成功:"+res.get(0));
System.out.println("发送短信,是否成功:"+res.get(1));
return res;
}
}
打印结果如下:
正在发送短信,内容为:boss,I want more money!!!
正在发送邮件,内容为:boss,I want more money!!!
发送短信失败
发送邮件成功
发送邮件,是否成功:true
发送短信,是否成功:false
发送消息结束!!!耗时:4052毫秒
3.总结
以上的例子,是本人对多线程入门的简单思考。当然,多线程远不止如此。还有锁,线程通信等等一系列问题。本篇文章只起一个入门的效果。