Java

java学习笔记#9-多线程

2018-08-11  本文已影响0人  edwin1993

多线程概念

多线程示例

Java对线程的支持体现在Thread类和Runnable接口

通过继承Thread类实现多线程,但是这种方式有一定的局限性。因为在java中只支持单继承,一个类一旦继承了某个父类就无法再继承Thread类,比如学生类Student继承了person类,就无法再继承Thread类创建的线程。
为了克服这种弊端,Thread类提供了另外一种构造方法Thread(Runnable target),其中Runnable是一个接口,它只有一个run()方法。

package Base.Multprocess;

/**
 * Created by Edwin_1993 on 2018/8/10.
 */
public class ThreadExample extends Thread {
    public void run(){
        System.out.println(getName() + " threadExample");
        int count = 0;
        boolean keepRunning = true;
        while(keepRunning){
            System.out.println((getName()+ " num:" + ++count));

            if (count == 100){
                keepRunning = false;
            }
            if (count%10 == 0){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        System.out.println(getName()+ " end");
    }

    
    public static void main(String args[]){
        Thread thread = new ThreadExample();
        thread.setName("ThreadExample");

        thread.start();

        Thread runnableThread = new Thread(new RunnableExample(),"Ms Runnable");
        runnableThread.start();
    }
}

class RunnableExample implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " RunnableExample");
        int count = 0;
        boolean keepRunning = true;
        while (keepRunning) {
            System.out.println((Thread.currentThread().getName() + " num:" + ++count));

            if (count == 100) {
                keepRunning = false;
            }
            if (count % 10 == 0) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

多线程的停止方式

package Base.Multprocess;

/**
 * Created by Edwin_1993 on 2018/8/11.
 */
public class WrongWayStopThread extends Thread {
    public static void main(String args[]){
        WrongWayStopThread wrongWayStopThread = new WrongWayStopThread();
        System.out.println("Thread starting ...");
        wrongWayStopThread.start();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread interrupting ...");
        wrongWayStopThread.interrupt();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread ending ...");
    }

    public void run(){
        while (true){
//        while (!this.isInterrupted()){
            System.out.println("Thread is running ...");
            long time = System.currentTimeMillis();
            while((System.currentTimeMillis() - time) < 1000){

            }
        }
    }
}

上述run方法改写后相当于使用了退出标志。

    public void run(){
//        while (true){
        while (!this.isInterrupted()){
            System.out.println("Thread is running ...");
            long time = System.currentTimeMillis();
            while((System.currentTimeMillis() - time) < 1000){

            }
        }
    }

使用sleep()方法,线程进入了阻塞状态,此时再调用interrupte方法会使得interrupt状态被清除,使得this.isInterrupted()无效,且使得sleep方法被中断:InterruptedException 。

    public void run(){
//        while (true){
        while (!this.isInterrupted()){
            System.out.println("Thread is running ...");
            long time = System.currentTimeMillis();
            while((System.currentTimeMillis() - time) < 1000){

            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
package Base.Multprocess;

/**
 * Created by Edwin_1993 on 2018/8/11.
 */
public class ArmyRunnable implements Runnable{
//    volatile 保证了线程可以正确读取其它线程写入的值
//    一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
//
//    1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
//
//    2)禁止进行指令重排序
    volatile boolean keepRunning = true;

    @Override
    public void run() {
        while (keepRunning){
            for(int i = 0;i <5;i++){
                System.out.println(Thread.currentThread().getName() + "attack["+i+"]");
//                t
                Thread.yield();
            }
        }
        System.out.println(Thread.currentThread().getName() + "end attack");
    }
}

线程交互

private final Object lockObj = new Object();


public void transfer(int from ,int to, double amount){

//        通过synchronized进行互斥
        synchronized (lockObj){
//            if (energyBoxes[from] < amount){
//                System.out.println("not enought energy");
//                return;
//            }

//            满足while条件时,任务被阻挡,不去竞争CPU资源。
            while (energyBoxes[from] < amount){
                try {
                    lockObj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.print(Thread.currentThread().getName());
            energyBoxes[from] -= amount;
            System.out.printf("从 %d 转移 %10.2f 单位能量到 %d",from,amount,to);
            energyBoxes[to] += amount;
            System.out.printf("能量总合: %10.2f", getTotalEnergy());
        }

//        非互斥模式
//        if (energyBoxes[from] < amount){
//            System.out.println("not enought energy");
//            return;
//        }
//        System.out.print(Thread.currentThread().getName());
//        energyBoxes[from] -= amount;
//        System.out.printf("从 %d 转移 %10.2f 单位能量到 %d",from,amount,to);
//        energyBoxes[to] += amount;
//        System.out.printf("能量总合: %10.2f", getTotalEnergy());

//        唤醒所有在lockObj上等待的线程。
        lockObj.notifyAll();
    }

上述代码中
当运行条件不满足的时候,通过lockobj.wait()来将线程放入Wait set
当某一条线程顺利执行完成时,通过lockobj.notifyAll()来唤醒所有的等待线程。

上一篇下一篇

猜你喜欢

热点阅读