由于最近太忙,导致一直拖着没有更新,今天抽空更新一下博文。这篇文章是CVTE二面失败的编程题,我的一些想法,因为本人现在还是菜鸡,对多线程的学习和理解还远远不够,所以今天我的题解不一定正确,如果有大佬指正可以评论,或最好私聊我,万分感谢!
题目描述:系统有两个线程,一个线程是正常运行时的线程,一个线程是备用线程。系统正常时,只有一个线程在运行,备份线程线程不工作。当正常运行的线程崩溃后,备份线程能继续工作。(这道题在面试时,是由面试官口述,我简要记录。记录完后,面试官让我代码模拟一下。)
首先是对这道题的理解,因为我不是面试官,也不能百分百理解到他的意思(主要当时太紧张了,也没有去和面试官提出疑问,了解其具体的要求。后来面试官的进一步说明我也没理解到。)
我的理解有三种不同的情况:
1、一种是最简单的,即在正常工作线程意外崩溃后,启动另一个线程继续工作;
2、第二种是正常线程意外崩溃后,要把正常线程崩溃时正在处理的对象(可以是某个客户端发给后端的一个请求消息)交给备份线程继续处理;
3、第三种是最难的,即在正常线程崩溃后,不仅要把对象传递给备份线程,可能还需要定位到正常线程崩溃时执行到哪条指令,然后接着执行。(这个可能要深入理解JVM和并发知识,我暂时也不清楚能否实现)。
当然,不论哪种情况都要获取到异常(或错误)的信息。
#第一种理解:在正常工作线程意外崩溃后,启动另一个线程继续工作
(1)在一个线程崩溃后,启动另一个线程:
1)先定义一个意外异常类,模拟意外导致线程崩溃的意外异常:
public class AccidentException extends Exception {
//定义一个意外异常类
public AccidentException(String message) {
super(message);
}
}
2)定义一个线程类(实现Runnable接口):
import java.util.Random;
public class TestThreadBackup implements Runnable {
Thread normalThread , backupThread; //两个线程,一个正常线程,一个备份线程
static int accident ; //表示意外异常触发条件
Random random = new Random();
String working = "正在运行……";
@Override
public void run() {
try {
simulateRun();
}catch (AccidentException e){
System.out.println(e.getMessage());
backupThread.start();
}
}
private void simulateRun() throws AccidentException { //模拟运行抛异常
while ( Thread.currentThread().equals(normalThread) ){
threadWorking();
accident = random.nextInt(4); //返回0~3的随机数,当等于3时表示出现异常
if ( accident == 3 ){
throw new AccidentException("出现意外异常!");
}
}
while ( Thread.currentThread().equals(backupThread) ){
threadWorking();
}
}
private void threadWorking(){ //线程工作内容,两个线程的工作内容应该一致
System.out.println( Thread.currentThread().getName() + working );
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace(); //这里只是线程异常唤醒的异常,和题目无关
}
}
public TestThreadBackup(Thread normalThread, Thread backupThread) { //构造方法
this.normalThread = normalThread;
this.backupThread = backupThread;
}
}
3)放在main()里运行:
public static void main(String[] args) {
Thread normal , backup ;
TestThreadBackup testThreadBackup = new TestThreadBackup();
normal = new Thread(testThreadBackup);
backup = new Thread(testThreadBackup);
normal.setName("normal线程");
backup.setName("backup线程");
testThreadBackup.setNormalThread(normal);
testThreadBackup.setBackupThread(backup);
normal.start();
}
控制台结果:
当然,可以不区分正常线程或备份线程,就是一个线程异常(或错误)终止后,就去new一个新线程,然后start() 启动。
还有另一种比较不可行的方法,就是利用线程联合 join() ,即备份线程联合正常线程,如果正常线程异常终止后备份线程就可以执行,但是我觉得这样不如分开更符合题目要求。
还有第2、第3种理解,因为时间关系,先不写了,我再想想,看看能不能模拟出来。后续会更新。
(在搭建自己的网站后,会把文章迁移到自己的博客。)