线程
- 线程的三种状态(五种状态)
- 运行态(Running) ---> yield() ---> 就绪态
- 就绪态(Runnable)
- 阻塞态(Blocked)
sleep( ) / IO中断 / join( )
wait( ) ---> 等待池 ---> notify( ) / notifyAll( ) ---> 等待池
synchronized ---> 等锁池 ---> 抢锁池 ---> 就绪态
- Thread类有两个静态方法可以让正在执行的线程放弃对cup的占用
1.sleep - 让CPU的时候不考虑优先级,yield要考虑优先级。
2.yield - 让出CPU后进入就绪态,sleep让出CPU后进入阻塞态
public class Frame extends JFrame implements ActionListener{
private JButton aButton,bButton,cButton,dButton;
private Thread thread1,thread2;
public static final int Width = 80;
public static final int Height = 50;
public Frame(){
this.setSize(500,300);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(null);
aButton = new JButton("上传");
aButton.setBounds(20, 150, Width, Height);
bButton = new JButton("下载");
bButton.setBounds(140, 150, Width, Height);
cButton = new JButton("计算");
cButton.setBounds(260, 150, Width, Height);
cButton.setEnabled(false);//一开始禁用"计算"按钮
dButton = new JButton("关于");
dButton.setBounds(380, 150, Width, Height);
aButton.addActionListener(this);
bButton.addActionListener(this);
cButton.addActionListener(this);
dButton.addActionListener(this);
this.add(aButton);
this.add(bButton);
this.add(cButton);
this.add(dButton);
}
private void download(){
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void upload(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Frame().setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("上传")) {
aButton.setEnabled(false);
aButton.setText("上传中");
thread1= new Thread(()->{
upload();
aButton.setEnabled(true);
aButton.setText("上传");
});
thread1.start();
}
else if (command.equals("下载")) {
bButton.setEnabled(false);
bButton.setText("下载中");
thread2 = new Thread(new Runnable() {
@Override
public void run() {
download();
bButton.setEnabled(true);
bButton.setText("下载");
}
});
thread2.start();
}
else if (command.equals("计算")) {
}
else if (command.equals("关于")) {
JOptionPane.showMessageDialog(null, "load.....");
}
new Thread(() -> {
if (thread1 != null && thread2 != null) {
try {
thread1.join();
thread2.join();
cButton.setEnabled(true);
}
catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}).start();
}
}
线程同步
-
synchronized(隐式锁机制)有两种用法:
1.放在方法的前面,该方法值允许抢占到对象锁的线程进入执行
2.构造synchronized代码块(同步代码块),只允许抢占到对象锁的线程进入执行 -
Lock(显示锁机制)
private Lock lock = new ReentrantLock();
lock.lock();
.....
lock.unlock();
-
没有抢占到对象锁的线程在系统自动维护的等锁池中等待
如果抢到锁的线程释放了对象锁,那么这些等锁的线程就抢锁,谁抢到锁谁就进入同步代码块中执行,没有抢到的继续等待
基于synchronized关键字的锁机制是可重入的锁机制 -
join方法是一个阻塞式方法,表示等待线程结束
如果将join方法放到主线程,会导致其他线程被阻塞
package org.mobiletrain;
//import java.util.ArrayList;
//import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//线程同步问题
class BankAccount {
private double balance;
private Lock lock = new ReentrantLock();
public double getBalance() {
return balance;
}
//使用Java 5 以后的锁机制解决同步问题
public /*synchronized*/ void transfer(double money){
lock.lock();
System.out.println(Thread.currentThread().getName());
double newBalance = balance + money;
try {
Thread.sleep(1);
}
catch (InterruptedException e) {
}
balance = newBalance;
lock.unlock();
}
}
class AddMoneyHandler implements Runnable{
private BankAccount account;
private int money;
public AddMoneyHandler(BankAccount account,int money) {
this.account = account;
this.money = money;
}
@Override
public void run() {
//synchronized (account) {
account.transfer(money);
//}
}
}
public class Test01 {
public static void main(String[] args) throws InterruptedException {
//List<Thread> list = new ArrayList<>();
ExecutorService service = Executors.newFixedThreadPool(10);
BankAccount mainAccount = new BankAccount();
for (int i = 0; i < 100; i++){
service.execute(new AddMoneyHandler(mainAccount, 100));
//Thread t = new Thread(new AddMoneyHandler(mainAccount, 100));
//list.add(t);
//t.start();
}
service.shutdown();
//判断线程池里的线程有没有终止
while ( ! service.isTerminated()) {
}
//join方法是一个阻塞式方法,表示等待线程结束
//如果将join方法放到主线程,会导致其他线程被阻塞
//for (Thread thread : list) {
//线程对象的join()
//thread.join();
//}
System.out.println("账户余额:¥" + mainAccount.getBalance());
}
}
-
wait()是让线程暂停(进入对象等待池),然后释放对象的锁 --- 在等待池中的线程需要其他线程将其唤醒
-
设置优先级改变的是线程获得CPU调度的几率
-
装潢模式
将线程不安全的容器包装成线程安全的容器
List<String> list = Collections.synchronizedList(new ArrayList<>());
public static void main(String[] args) {
List<String> list = Collections.synchronizedList(new ArrayList<>());
//ArrayList是线程不安全的,因为它的方法没有加synchronized保护
//List<String> list = new ArrayList<>();
ExecutorService service = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++){
service.execute(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 100000; j++){
list.add("Hello");
}
}
});
}
service.shutdown();
while (! service.isTerminated()){
}
System.out.println(list.size());
}
网友评论