java 线程 try catch_Java线程-异常处理

在Java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉。这一点是通过java.lang.Runnable.run()方法声明(因为此方法声明上没有throw exception部分)进行了约束。但是线程依然有可能抛出unchecked exception,当此类异常抛出时,线程就会终结,而对于主线程和其他线程完全不受影响,且完全感知不到某个线程抛出的异常(也是说完全无法catch到这个异常)。JVM的这种设计源自于这样一种理念:“线程是独立执行的代码片断,线程的问题应该由线程自己来解决,而不要委托到外部。”基于这样的设计理念,在Java中,线程方法的异常(无论是checked还是unchecked exception),都应该在线程代码边界之内(run方法内)进行try catch并处理掉。下面看两个例子:

例子一:IOException是一个chedked exception,在这里看到了报错,编译不通过。

01cc6f251bdc7cab226563c604aa0e7b.png

例子二:想捕线程的非检查异常,发现也不能捕获

public class MyThread2 implements Runnable {

@Override

public void run() {

int i = 1/0; //此处会报非检查异常

}

public static void main(String[] args) {

try {

Thread t = new Thread(new MyThread2());

t.start();

} catch (Exception e) {

//想在外面捕获异常,但是获取不到

System.out.println("分母不能是零啊");

}

}

}

运行结果:

Exception in thread "Thread-0" java.lang.ArithmeticException: / by zero

at org.burning.sport.javase.thread.MyThread2.run(MyThread2.java:11)

at java.lang.Thread.run(Thread.java:745)

从运行结果看到,catch代码块中并没有打印输出

那如果我们需要捕获线程跑出的异常并做处理的话改怎么办呢?

方法一:在run()方法中用try catch来捕获这个异常并做处理

public class MyThread implementsRunnable {

@Overridepublic voidrun() {try{int i = 1/0;

}catch(Exception e) {

System.out.println("这里有问题,可以通知给其他人:" +e); //这里可以做捕获异常后的其他操作,比如发消息给第三方

}

}public static voidmain(String[] args) {

Thread t= new Thread(newMyThread());

t.start();

}

}

结果:

这里有问题,可以通知给其他人:java.lang.ArithmeticException: / by zero

方法二:我们想在线程边界之外捕获这个异常的(run()方法之外)的话,那我们就要用到Java给我们提供的UncaughtExceptionHandler处理方法

步骤一:定义一个自己的异常处理器

packageorg.burning.sport.javase.thread.exception;public class MyUncatchException implementsThread.UncaughtExceptionHandler {

@Overridepublic voiduncaughtException(Thread t, Throwable e) {

System.out.println("当前线程的名字:" +t.getName());

System.out.println("发生了什么问题:" +e );

}

}

步骤二:在线程启动前设置自定义的异常处理器

packageorg.burning.sport.javase.thread.exception;public class ExceptionThread implementsRunnable {

@Overridepublic voidrun() {

System.out.println("将要悲剧了");int i = 1/0;

}public static voidmain(String[] args) {

Thread t= new Thread(newExceptionThread());//这里设置自定义的异常处理器

t.setUncaughtExceptionHandler(newMyUncatchException());

t.start();

}

}

结果:

将要悲剧了

当前线程的名字:Thread-0

发生了什么问题:java.lang.ArithmeticException: / by zero

小结:

如果在run方法中没有发生异常,那么就不会去运行MyUncatchException

如果用线程池来启动线程的话还可以用ThreadFactory来设置异常处理器

步骤一:同上

步骤二:自定义一个ThreadFactory

packageorg.burning.sport.javase.thread.exception;importjava.util.concurrent.ThreadFactory;public class HandlerThreadFactory implementsThreadFactory {

@OverridepublicThread newThread(Runnable r) {

Thread t= newThread(r);

System.out.println("线程名称:" +t);

t.setUncaughtExceptionHandler(newMyUncatchException()); //设置异常处理器

System.out.println("好恐怖:" +t.getUncaughtExceptionHandler());returnt;

}

}

步骤三:通过线程池启动线程

packageorg.burning.sport.javase.thread.exception;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;public class ExceptionThread implementsRunnable {

@Overridepublic voidrun() {

System.out.println("将要悲剧了");int i = 1/0;

}public static voidmain(String[] args) {

ExecutorService exec= Executors.newCachedThreadPool(newHandlerThreadFactory());

exec.execute(newExceptionThread());

}

}

结果:

线程名称:Thread[Thread-0,5,main]

好恐怖:org.burning.sport.javase.thread.exception.MyUncatchException@4b9af9a9

将要悲剧了

线程名称:Thread[Thread-1,5,main]

好恐怖:org.burning.sport.javase.thread.exception.MyUncatchException@34d6cbd5

当前线程的名字:Thread-0

发生了什么问题:java.lang.ArithmeticException: / by zero

参考:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的问题是关于Java线程的存钱取钱问题。这是一个经典的多线程同步问题,可以通过使用synchronized关键字来实现线程安全。下面是一个简单的示例代码: ```java public class BankAccount { private int balance; public BankAccount(int balance) { this.balance = balance; } public synchronized void deposit(int amount) { balance += amount; System.out.println("Deposit successful. Balance: " + balance); } public synchronized void withdraw(int amount) { if (balance < amount) { System.out.println("Withdraw failed. Insufficient balance."); return; } balance -= amount; System.out.println("Withdraw successful. Balance: " + balance); } } public class Main { public static void main(String[] args) { BankAccount account = new BankAccount(1000); // Create two threads to simulate deposit and withdraw Thread depositThread = new Thread(() -> { for (int i = 0; i < 5; i++) { account.deposit(100); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); Thread withdrawThread = new Thread(() -> { for (int i = 0; i < 5; i++) { account.withdraw(200); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); depositThread.start(); withdrawThread.start(); } } ``` 在这个示例代码中,我们创建了一个银行账户类BankAccount,并在其中实现了deposit和withdraw方法,并使用synchronized关键字来保证线程安全。 在main方法中,我们创建了两个线程来模拟存款和取款操作,每个线程执行5次操作。我们使用Thread.sleep方法来模拟每个操作之间的间隔,以便更好地观察多线程操作的结果。 当多个线程同时访问BankAccount对象的deposit和withdraw方法时,synchronized关键字可以确保每个方法只能被一个线程访问,从而避免了竞争条件和数据不一致的问题。 希望这个示例代码能够回答您的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值