java基础笔记(8)

java的多线程

进程:程序的执行过程,持有内存资源

线程:是系统的最小执行单元,共享进程的资源

线程之间可以互斥、也可以同步;

Thraed类:

扫描二维码关注公众号,回复: 7896046 查看本文章

通过一个案例来了解线程Thread类和Runnable接口的运用:

案例须知:

1、实现舞台线程(继承Thread类)

2、实现军队线程,通过调用军队线程实现农民和政府双军队线程,将军队交战线程放到舞台线程中开始运行,双线程是交叉运行;(继承Runnable接口)

3、实现一个英雄进场线程(继承Thread类),在双线程结束后将英雄入场线程放到舞台线程中运行,运行后结束后舞台线程随之结束;

军队线程:

package com.thread;

public class Army implements Runnable {
    volatile boolean keepRunning =true;//保证了线程可以读取其他线写入的值
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(keepRunning) {
            for(int i = 0;i<5;i++) {
                System.out.println(Thread.currentThread().getName()+"进攻对方["+i+"]次");
                Thread.yield();//让出处理器时间,下次进攻是谁还不一定呢
            }
        }
        System.out.println(Thread.currentThread().getName()+"结束了战斗");
    }

}

英雄进场线程:

package com.thread;

public class Hero extends Thread {
    public void run() {
        System.out.println(Thread.currentThread().getName()+"加入了战斗");
        for(int i = 0;i<10;i++) {
            System.out.println(Thread.currentThread().getName()+"释放技能:“捞人自捞”");
            
        }
        System.out.println(Thread.currentThread().getName()+"结束了战斗");
    }
}

舞台线程:

package com.thread;

public class Stage extends Thread {
    public void run() {
        Army armyOfZf = new Army();
        Army armyOfNm = new Army();
        Thread armyOfZfTh = new Thread(armyOfZf,"政府");
        Thread armyOfNmTh = new Thread(armyOfNm,"农民");
        armyOfNmTh.start();
        armyOfZfTh.start();
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        armyOfZf.keepRunning = false;
        armyOfNm.keepRunning = false;
        Thread mrya = new Hero();
        mrya.setName("余桉");
        System.out.println("农民和政府打的不可开交时"+mrya.getName()+"冲入了战场!!!");
        try {
            Thread.sleep(50);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        mrya.start();
        try {
            mrya.join();//等待mrya线程运行完后,程序才会继续执行;
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        try {
            armyOfNmTh.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Stage test = new Stage();
        test.start();
    }

}

注意:这里的案例我们停止线程是用了一个一个布尔值keepRunning,将改变其值使得线程运行完毕,而java本身的Thread类有提供一个stop()的线程停止方法,但这个方法是不正确的停止方法,因为这个是“猝死”类型的停止方法,会让线程直接停止,这样会使得我们没法输出提示信息,也没能有效地处理线程的后=后续清理工作;因此说这个方法是不正确的停止方法;

两个线程发生争用条件:两个不同的线程同时访问同一资源,在线程一把原本的资源改了,但是资源并没来得及传入硬盘而是只存在于内存中,此时若是切换到线程2.线程二对该资源操作完成后又切换到线程一,线程一继续刚没结束的上下文,把刚修改存在内存中的资源一再返回硬盘中,此时就会使得线程二对于资源的操作修改被覆盖,导致资源的状态和我们想要的不一样;

线程互斥和同步:互斥即对线程进行加锁,需等线程解锁后别的线程才可以操作该共享对象;同步是指线程对共享对象的使用,需要让其共享资源满足于什么条件下才可以使用,此时线程会调用wait()方法进入等待,等别的线程操作完共享对象,达到该条件后再触发notifyAll(),唤醒等待状态的所有线程;

先创建一个共享对象:

 线程开始之前:

通过synchronized关键字定义临界端,wait()使得线程进入等待阶段,在Wait set集合中进行等待,别的线程可以进入这个临界端,当运行notifyAll()时唤醒所有线程;

猜你喜欢

转载自www.cnblogs.com/lzj-learn/p/11868663.html
今日推荐