Java -- 线程

线程

  • 线程的三种状态(五种状态)
    1. 运行态(Running) ---> yield() ---> 就绪态
    2. 就绪态(Runnable)
    3. 阻塞态(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 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 list = Collections.synchronizedList(new ArrayList<>());
public static void main(String[] args) {
        List list = Collections.synchronizedList(new ArrayList<>());
        //ArrayList是线程不安全的,因为它的方法没有加synchronized保护
        //List 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());
    }       

你可能感兴趣的:(Java -- 线程)