第九节 Java多线程

多线程简介

线程的基本知识

线程是程序运行的基本单位,一个程序可以运行多个线程,可以提高程序的运行效率。

线程是具有一定顺序的指令序列,存放方法中定义局部变量的栈和一些共享数据。

线程是相互独立的,任何线程都不能访问其他线程的局部变量。

如果两个线程同时访问一个方法,那每个线程各自得到此方法的一个拷贝。

Java实现线程的两种方式

派生Thread类

实现Runable接口。

创建线程的两种方法

Thread创建线程

/*
    继承Thread类创建线程
 */
class MyThread extends Thread{
    public MyThread(){}
    public MyThread(String name){
        super(name);
    }
    //重载run函数
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(this.currentThread().getName()+"="+i);
        }
    }
}

//创建线程
    public static void main(String[] args) {
        //创建线程
        MyThread myThread = new MyThread("线程1");
        myThread.start();
        MyThread myThread1 = new MyThread("线程2");
        myThread1.start();
    }

实现Runable接口创建线程

/*
    实现Runable接口来创建线程
    Thread类中有以下两个构造方法:
        Thread(Runnable target)
        Thread(Runnable target, String name)
 */

class MyRunable implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName()+"="+i);
        }
    }
}

//创建线程
    public static void main(String[] args) {
        Thread myThread = new Thread(new MyRunable(),"线程1");
        myThread.start();
        Thread myThread1 = new Thread(new MyRunable(),"线程2");
        myThread1.start();
    }

等待线程结束

通过isAlive判断

class Main{
    public static void main(String[] args) throws InterruptedException {
        Thread myThread = new Thread(new MyRunable(),"线程1");
        myThread.start();
        //判断如果第一个线程在执行,那么让主线程等待,一直执行完线程1之后,再往下执行
        while (myThread.isAlive()){
            Thread.sleep(1);
        }
        //执行完线程1,执行线程2
        MyThread myThread1 = new MyThread("线程2");
        myThread1.start();
    }
}

通过join方法

class Main{
    public static void main(String[] args) {
        Thread myThread = new Thread(new MyRunable(),"线程1");
        myThread.start();
        /*
            join方法
                join()-myThread.join()
                join(微秒,纳秒)——myThread.join(10,1000)
         */
        try {
            myThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //执行完线程1,执行线程2
        MyThread myThread1 = new MyThread("线程2");
        myThread1.start();
    }
}

线程的声明周期

线程的生命周期

线程一共有四种状态:
1. 创建状态
创建在new之后,start之前。
2. 可运行状态
可运行状态在对象执行start之后
3. 不可运行状态
不可运行状态,指线程处于被挂起或者阻塞的状态,例如调用wait()后,线程可能进入阻塞状态;调用线程的notify或者notifyAll后才会再次返回到可运行状态。
4. 退出状态
线程可以在任何状态下调用stop方法进入退出状态,除此之外,线程run完,即执行完也会自动进入退出状态。

线程状态转换
线程状态转换

线程状态转换函数
线程状态转换函数

其中stop,suspend和resume方法已经不提倡使用。
suspend由wait方法替代
resume方法由sleep方法替代
线程退出采用自然中止方法,不建议人工调用stop方法。

线程调度(优先级)

多线程应用程序的每个线程的优先级可能不同。

当多个线程等待CPU时间片时,优先级高的能抢占CPU并执行

java中,CPU抢占式的。因此,优先级高的执行的抢占CPU次数较多。

优先级数字1-10

优先级常数:Thread.NORM_PRIORITY,Thread.MAX_PRIORITY,Thread.MIN_PRIORITY

class Main{
    public static void main(String[] args) {
        Thread myThread = new Thread(new MyRunable(),"线程1");
        Thread myThread1 = new Thread(new MyRunable(),"线程2");
        myThread.setPriority(10);//设置优先级1-10
//        myThread.setPriority(Thread.MAX_PRIORITY);
        myThread1.setPriority(1);
//        myThread1.setPriority(Thread.MIN_PRIORITY);

        myThread.start();
        myThread1.start();
    }
}

线程的同步

Java应用程序的多线程可以共享资源,当线程以并发模式访问共享数据时,共享数据可能会出现冲突。

java引入线程同步,可以实现共享数据的一致性。

在线程异步的情况下,同一个时刻一个线程修改数据,而另一个线程读取数据,那么读取的数据将会是错误数据。

比如,线程1和线程2都出售火车票,两个线程共享票数,出现以下情况就会出错:
1. 线程1发现票T
2. 线程2发现票T,售出
3. 线程1售出T。
如果线程按照上面顺序出售车票,那么车票T被出售了两次。

java通过sysnchronized关键字锁住共享代码区,从而实现线程同步。

几种同步实现方式
1. 同步方法

class Main{
    public static void main(String[] args) {
        Acount acount = new Acount();
        acount.setCount(100);
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName());
                    acount.show();
                    acount.addMoney(100);
                    System.out.println("----");
                }
            }
        },"线程1----").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName());
                    acount.show();
                    acount.subMoney(20);
                    System.out.println("----");
                }
            }
        },"线程2----").start();


    }
}
//使用同步方法
class Acount{
    private int count;
    //存钱
    public synchronized void addMoney(int money){
        count+=money;
        System.out.println("存进="+money+"元");
    }
    //取钱
    public synchronized void subMoney(int money){
        count-=money;
        System.out.println("取钱="+money+"元");
    }
    //查询余额
    public void show(){
        System.out.println("余额="+count+"元");
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}
  1. 同步代码块
class Acount{
    private int count;
    //存钱
    public void addMoney(int money){
        synchronized (this) {
            count += money;
            System.out.println("存进="+money+"元");
        }

    }
    //取钱
    public  void subMoney(int money){
        synchronized (this) {
            count -= money;
            System.out.println("取钱="+money+"元");
        }
    }
    //查询余额
    public void show(){
        System.out.println("余额="+count+"元");
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

synchronized关键字

synchronize修饰的方法和 synchronize(this) 都是锁住自己本身的对象 而synchronize(class) synchronize(object) 都是锁别的对象

猜你喜欢

转载自blog.csdn.net/lay_ko/article/details/79693289