package com.company.calcul; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Thread1 { public static void main(String[] args) { ReentrantLock reentrantLock = new ReentrantLock(); Condition condition1 = reentrantLock.newCondition(); Condition condition2 = reentrantLock.newCondition(); Condition condition3 = reentrantLock.newCondition(); Thread threadA = new Thread(() -> { reentrantLock.lock(); try { condition1.await(); System.out.println("A"); condition2.notify(); } catch (InterruptedException e) { e.printStackTrace(); } reentrantLock.unlock(); }); Thread threadB = new Thread(() -> { reentrantLock.lock(); try { condition2.await(); System.out.println("B"); condition3.notify(); } catch (InterruptedException e) { e.printStackTrace(); } reentrantLock.unlock(); }); Thread threadC = new Thread(() -> { reentrantLock.lock(); try { condition3.await(); System.out.println("C"); } catch (InterruptedException e) { e.printStackTrace(); } reentrantLock.unlock(); }); threadA.start(); threadB.start(); threadC.start(); condition1.notify(); } }
时间: 2024-02-14 09:31:14 浏览: 119
这段代码使用了ReentrantLock和Condition来实现线程间的通信。在这个例子中,有三个线程A、B、C,它们依次打印字母"A"、"B"、"C"。
代码中首先创建了一个ReentrantLock对象reentrantLock,以及三个Condition对象condition1、condition2、condition3。然后创建了三个线程,分别对应字母"A"、"B"、"C"。
在线程A的run方法中,先调用reentrantLock.lock()获取锁,然后调用condition1.await()释放锁并进入等待状态,直到被其他线程调用condition1.notify()唤醒。唤醒后打印字母"A",并调用condition2.notify()唤醒线程B,最后调用reentrantLock.unlock()释放锁。
线程B和线程C的逻辑类似,先获取锁,然后进入等待状态,直到被唤醒后打印相应的字母,并唤醒下一个线程。
最后,在主线程中启动三个子线程,并调用condition1.notify()唤醒线程A开始执行。
需要注意的是,notify()方法只能唤醒一个等待的线程,所以在这里使用了三个Condition对象来实现三个线程的顺序执行。
相关问题
package com.company.calcul; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Thread1 { public static void main(String[] args) { ReentrantLock reentrantLock = new ReentrantLock(); Condition condition1 = reentrantLock.newCondition(); Condition condition2 = reentrantLock.newCondition(); Condition condition3 = reentrantLock.newCondition(); Thread threadA = new Thread(() -> { reentrantLock.lock(); try { condition1.await(); System.out.println("A"); condition2.signal(); } catch (InterruptedException e) { e.printStackTrace(); } reentrantLock.unlock(); }); Thread threadB = new Thread(() -> { reentrantLock.lock(); try { condition2.await(); System.out.println("B"); condition3.signal(); } catch (InterruptedException e) { e.printStackTrace(); } reentrantLock.unlock(); }); Thread threadC = new Thread(() -> { reentrantLock.lock(); try { condition3.await(); System.out.println("C"); } catch (InterruptedException e) { e.printStackTrace(); } reentrantLock.unlock(); }); threadA.start(); threadB.start(); threadC.start(); condition1.signal(); } } 程序无法执行,为什么?
这段代码无法正确执行是因为在调用Condition的signal()方法之前还没有获取到锁。
在代码中,线程A、B、C都会先调用reentrantLock.lock()获取锁,然后进入等待状态,并在等待状态中调用conditionX.await()方法来释放锁并等待被唤醒。
但是,在主线程中启动三个子线程之后,立即调用了condition1.signal()方法来唤醒线程A,这时候线程A还没有开始运行,也没有获取到锁,所以调用signal()方法会抛出IllegalMonitorStateException异常。
为了解决这个问题,可以在启动子线程之后,先调用reentrantLock.lock()获取锁,然后再调用condition1.signal()方法唤醒线程A,最后释放锁。这样可以确保线程A在调用signal()方法之前已经获取到了锁。
修正后的代码如下:
```
package com.company.calcul;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Thread1 {
public static void main(String[] args) {
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition1 = reentrantLock.newCondition();
Condition condition2 = reentrantLock.newCondition();
Condition condition3 = reentrantLock.newCondition();
Thread threadA = new Thread(() -> {
reentrantLock.lock();
try {
condition1.await();
System.out.println("A");
condition2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
});
Thread threadB = new Thread(() -> {
reentrantLock.lock();
try {
condition2.await();
System.out.println("B");
condition3.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
});
Thread threadC = new Thread(() -> {
reentrantLock.lock();
try {
condition3.await();
System.out.println("C");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
});
reentrantLock.lock();
try {
threadA.start();
threadB.start();
threadC.start();
condition1.signal();
} finally {
reentrantLock.unlock();
}
}
}
```
在修正后的代码中,主线程在启动子线程之前先获取锁,然后再启动子线程并调用condition1.signal()方法唤醒线程A,最后释放锁。这样就能保证线程A在调用signal()方法之前已经获取到了锁。
优化一下java import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random; import javax.swing.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import java.awt.BorderLayout; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; public class sumitup extends JFrame implements ActionListener{ JTextField rValue = new JTextField(8); JTextField lValue = new JTextField(8); JTextField result = new JTextField(8); JButton calcul = new JButton("Check"); sumitup() { /*布局设计*/ setTitle("Welcome to sum it up"); setLayout(null); setBounds(200, 100, 1200, 800); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel myTitle = new JPanel(); myTitle.add(new JLabel("Enter two operands,result and click on 'Check'")); JPanel myText = new JPanel(); myText.add(rValue); myText.add(new JLabel(" + ")); myText.add(lValue); myText.add(new JLabel(" = ")); myText.add(result); Box myMain = Box.createVerticalBox(); Component strut1 = Box.createVerticalStrut(5); Component strut2 = Box.createVerticalStrut(30); myMain.add(strut1); myMain.add(myTitle); myMain.add(myText); myMain.add(strut2); myMain.setBounds(360, 600, 300, 100); add(myMain); calcul.setBounds(450, 700, 100, 50); add(calcul);
可以采用以下方式优化代码:
1. 不建议使用 null 布局。可以使用其他布局管理器,如 BorderLayout、GridLayout、GridBagLayout 等,以便更好地控制组件的位置和大小。
2. 尽量避免使用通配符导入,因为这会增加代码的混淆度和可读性。可以手动导入需要的类,或者使用 IDE 的自动导入功能。
3. 可以将一些常用的类或方法封装在单独的类中,以便于重用和维护。
4. 可以将一些重复的代码块抽象成方法,以便于复用和减少代码冗余。
5. 可以添加异常处理机制,以防止程序出现异常而崩溃。
阅读全文