Java多线程(二)

在线程中启动启动其他线程

线程通过调用star()方法将启动该线程,使之从新建状态进入就绪队列排队。一旦轮到它享用CPU资源的时候,就可以脱离创建它的主线程,开始自己的生命周期。

线程一计算完1+2+…+50,线程二继续计算51+52+…+100。

package com.thread;

public class MultiThread_StartOtherThread {

    public static void main(String[] args) {

        Calculate cal = new Calculate();
        Thread thread1 = new Thread(cal);
        thread1.setName("1");
        thread1.start();
    }

}

class Calculate implements Runnable{

    int i=1 , sum=0;//线程共享数据

    public void run() {
        Thread thread =Thread.currentThread(); 
        while(i<=100){
            sum = sum+i;

            if(i==50){
                System.out.println(thread.getName()+":"+sum);

                Thread thread2 = new Thread(this);//thread2与thread1的目标对象相同
                thread2.setName("2");
                thread2.start();

                i++;
                return;//thread1死亡
            }
            i++;
            try{
                Thread.sleep(20);
            }catch(InterruptedException e){}
        }
        System.out.println(thread.getName()+":"+sum);
    }

}

线程的interrupt()方法

interrupt()方法的功能是中断线程。

若当前线程没有中断它自己或当前线程无法修改该线程,则该线程的checkAccess方法会被调用,这可能抛出SecurityException。

若线程在调用Object类的wait(),join(),sleep()方法中受阻,则其中断状态将被清除,收到一个InterruptException异常。

若该线程在可中断通道上的I/O操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程收到一个ClosedByInterruException异常。

使用interrupt()中断线程方法,让一个线程唤醒另一个休眠线程。

package com.thread;

public class MultiThread_interrupt {

    public static void main(String[] args) {

        Room room = new Room();
        room.student.start();
        room.teacher.start();
    }

}

class Room implements Runnable{

    Thread student,teacher;
    Room(){
        student = new Thread(this);
        teacher = new Thread(this);
        student.setName("Student");
        teacher.setName("Teacher");
    }
    public void run() {

        if(Thread.currentThread()==student){
            try{
                System.out.println("Student is sleeping");
                Thread.sleep(1000*60);
            }catch(InterruptedException e){
                System.out.println("wake up");
            }
            System.out.println("listen class");
        }
        else if(Thread.currentThread()==teacher){
            System.out.println("teacher say begin class");
            try{
                Thread.sleep(200);
            }catch(InterruptedException e){}
            student.interrupt();//唤醒Student
        }
    }

}

线程的同步

一个Java程序的多线程间可以共享数据,就存在两个或多个线程同时使用相同且有限资源的可能性,这样就可能产生冲突。
多线程的同步,就是使多个访问同一个数据的线程,按序进行,以免数据出错。当一个线程处理某数据时,其他欲访问改数据的线程必须等待,直到前一线程处理改数据完毕。

Java采用synchronized关键词来实现同步。其原理是赋予该对象唯一的一把“钥匙”(也叫“同步锁”),当多个线程进入对象,只有取得对象钥匙的进程,才可以访问同步方法,其他线程必须等待,直到该线程用wait()方法放弃这把钥匙,并执行notifyAll()方法通知所有因使用这个同步方法而处于等待的线程,让它们结束等待。
notifyAll():中断的线程会从中断处继续执行这个同步方法,并遵循“先中断先执行”的原则。

模拟三人排队买票,张三,李四,王五。售票员只有三张10元的钱,票10元一张。张三拿着一张50元排第一,李四拿着一张20元排第二,王五拿着一张10元排最后。

package com.thread;

public class MultiThread_synchronized {

    public static void main(String[] args) {
        Queue queue = new Queue();
        queue.zs.start();
        queue.ls.start();
        queue.ww.start();

    }

}

class Queue implements Runnable{
    Saler s;
    Thread zs,ls,ww;

    Queue(){
        s=new Saler();
        zs = new Thread(this);
        ls = new Thread(this);
        ww = new Thread(this);
    }

    public void run(){
        if(Thread.currentThread()==zs){
            s.charge(50);
        }else if(Thread.currentThread()==ls){
            s.charge(20);
        }else if(Thread.currentThread()==ww){
            s.charge(10);
        }

    }
}

class Saler{
    int number10=3,number20=0,number50=0;

    public synchronized void charge(int money){

        if(money==10){
            number10++;
            System.out.println("收您10元");
        }
        else if(money==20){
            while(number10<1){
                try{
                    wait();
                }catch(InterruptedException e){}
            }
            number10--;
            number20++;
            System.out.println("收您20,找零10");
        }
        else if(money==50){
            while((10*number10+20*number20)<40){
                try{
                    wait();
                }catch(InterruptedException e){}
            }

            number50++;
            if(number20>0){
                number20--;
                number10=number10-2;
            }else{
                number10=number10-4;
            }
            System.out.println("收您50,找零40");
        }

        notifyAll();

    }
}
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页