多线程:

程序运行时:启动了两个线程:

Main线程:调用main方法,执行main方法。

GC线程:在main线程运行时运行,回收程序运行之中的垃圾。

线程:一条执行路径。多线程完成多个功能并发并发执行的效果。

多线程之间乱系执行、同一线程内部顺序执行的。

写多线程:

1. 继承自Thread类,重写run方法。然后用Threadstart方法启动线程。

2. 实现Runnable接口,实现run方法。然后用Threadstart方法启动线程。

两种方式的区别:

1. 第一种使用简单。

2. 第二种不受java单继承的限制。一般来说,都是用第二种。

线程中常用的方法:线程中的已过时方法禁止使用。其他类中的过时方法不建议使用。

1. start:启动一个新线程。启动之后jvm会自动执行run方法。

2. run:线程启动之后执行的方法。

3. setNamegetName:自动命名,Thread-0,1

4. currentThread:得到当前运行的线程。

5. getPriority()setPriority 得到和设置当前线程的优先级。优先级1-10,如果不指定默认是5. 理论上,谁优先级高,谁被cpu调度的可能性就大。但是优先级低的并不是不执行。资源不足的时候才有效果。

6. setDaemon:将线程置为守护线程。只能在线程start之前调用。一般用于为其他线程提供服务,比如GC。守护线程会随着其他非守护线程的结束而结束。isDaemon可以用于判断某个线程是否是守护线程。

7. sleep:让当前线程停止执行(休眠)一段时间。

8. join:如果在A线程中B线程join进来,则现在执行B的内容,直到B执行完毕才继续执行A。比如A是显示数据  B是收集收据。

9. yield:让位:让出执行权,和其他线程争夺资源,谁拿到cpu时间片谁执行。

线程的状态图:说明 run方法结束,新线程结束。

线程_多线程

package day16;
import java.util.ArrayList;
import java.util.Vector;
public class Bank {
    public static void main(String[] args) {
        // 创建一个账户
        Account account = new Account();
        // 你和女朋友操作同一个账户
        Person1 you1 = new Person1(account);
        Person1 yourGF1 = new Person1(account);
        Thread thYou1 = new Thread(you1);
        Thread thYourGF1 = new Thread(yourGF1);
        // 你和女朋友同时去取钱。
        thYou1.start();
        thYourGF1.start();
              
        // 存钱线程
        Person2 you2 = new Person2(account);
        Person2 yourGF2 = new Person2(account);
        Thread thYou2 = new Thread(you2);
        Thread thYourGF2 = new Thread(yourGF2);
        thYou2.start();
        thYourGF2.start();
              
              
              
        try {
            Thread.sleep(5000);// 确保账户操作完毕
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("最终账户余额:"+account.balance);
    }
}
class Account{
    private ArrayList list;
    private Vector v ;
    public int balance = 2000;
    private Object obj1 = new Object();
//  private Object obj2 = new Object();
    // 取款
    public /*synchronized*/ void withdraw(){// 同一时间只能有一个线程访问。
        synchronized (obj1) {
            int temp = balance;
            temp = temp - 800;
            try {
                Thread.sleep(1000);// 模拟网络延迟。
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            balance = temp;
            System.out.println(Thread.currentThread().getName()+"取款");
//          while(true){}
        }
    }
    // 存款
    public /*synchronized*/ void deposit(){// 同一时间只能有一个线程访问。
        synchronized (obj1) {
            int temp = balance;
            temp = temp + 800;
            try {
                Thread.sleep(1000);// 模拟网络延迟。
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            balance = temp;
            System.out.println(Thread.currentThread().getName()+"存款");
        }
    }
}
class Person1 implements Runnable{
    // 人要自己的账户。
    private Account account ;
    public Person1(Account account){
        this.account = account;
    }
    @Override
    public void run() {
        account.withdraw();
    }
}
class Person2 implements Runnable{
    // 人要自己的账户。
    private Account account ;
    public Person2(Account account){
        this.account = account;
    }
    @Override
    public void run() {
        account.deposit();
    }
}

线程相关的常用类:

1. Timer:定时器、调度器、计时器

2. TimerTask:定时任务。

线程间的同步:本质:把异步转化为同步,把并行转为串行。

方式:

1. 同步语句块:synchronized(obj){}

2. 同步方法:在方法前加synchronized修饰符,拿到的仍然是本类对象的锁。

难点:不容易测出来。

对象锁:每个对象都有一把锁。同步锁、互斥锁

package day16;
import java.awt.BorderLayout;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import com.sun.awt.AWTUtilities;
public class Logo extends JFrame{
    /** logo下标 **/
    private int niIndex = 1;
    /** 显示图片内容的标签 **/
    private JLabel lbShow;
    /** 计时器 **/
    private Timer timer;
    public Logo(){
        JPanel pnBasic = new JPanel();
        pnBasic.setLayout(new BorderLayout());
          
        lbShow = new JLabel();
        pnBasic.add(lbShow,BorderLayout.CENTER);
        lbShow.setIcon(new ImageIcon("fff/role1/1.png"));
          
        setContentPane(pnBasic);
        setTitle("欢迎界面");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(200,200,410,320);
        // 透明
        setUndecorated(true);
        AWTUtilities.setWindowOpaque(this, false);
        setVisible(true);
        // 定义定时器
        timer = new Timer();
        // 1.重复执行的任务 2.延迟多长时间执行 3.执行频率
        timer.schedule(new LogoMonitor(),1000,500);
    }
      
    private class LogoMonitor extends TimerTask{
        @Override
        public void run() {
            if(niIndex<7){
                niIndex++;
                lbShow.setIcon(new ImageIcon("fff/role1/"+niIndex+".png"));
            }else{
                timer.cancel();
                dispose();
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("进入主界面");
            }
        }
    }
      
    public static void main(String[] args) {
        new Logo();
    }
}