手记

线程学习笔记(二)——线程的控制方法及线程的同步

在之前的笔记中记录了线程与进程的区别,以及线程的启动方式,接下来就是关于线程的一些控制方法。
最主要的的中断线程的方法有两个:

Thread.sleep(long ms);//线程休眠
Thread.yield();//放弃CPU使用权

sleep()的参数是休眠的时长,为毫秒数,方法执行后,该线程会休眠该时长,当休眠结束后,该线程会重新参与竞争CPU的使用权,但是不是一休眠结束就可以抢占到CPU,所以实际上,该线程的实际不工作时长会大于设定的休眠时长。

yield()是该线程主动让出CPU的使用权,但是在让出之后同样会参与竞争,因此即使某线程调用了yield()方法,也可能继续占用CPU。

还可以设置某一个线程的优先级:

getPriority()//获取线程的优先级
setPriority()//设置线程的优先级
在这里要说明一下,设置大的优先级只能增大线程竞争到CPU的概率,但并不是绝对,每个线程都能抢占到CPU,因为线程的最大特点就是不确定性

第二个内容就是关于同步代码块。当多个线程公用同一个线程体时,容易出现数据丢失的情况。此时就需要用到同步锁来保护代码。
我们看一下下面的代码:

public class MyThread implements Runnable {
    int i = 100;
    @Override
    public void run() {
        while(true){
            //获取当前正在执行的线程的名字
            System.out.println(Thread.currentThread().getName()+"---"+ i);
            i--;
            Thread.yield();
            if(i<0){
                break;
            }

        }
    }
}
public class Test {

    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread t1 = new Thread(myThread);
        Thread t2 = new Thread(myThread);
        t1.setName("线程a");
        t2.setName("线程b");
        t1.start();
        t2.start();
    }
}

当Test.java运行时,会出现下面的运行结果:

线程a---100
线程b---100
线程a---99
线程b---98
线程a---97
线程a---95
线程b---96
线程a---94
线程b---92
……

可以看到数据出现了丢失。我们可以使用同步锁来避免这样的情况出现:

同步锁要使用关键字synchronized

下面我们将MyThread线程体中的代码用该关键字包裹

public class MyThread implements Runnable {
    int i = 100;
    @Override
    public void run() {
        while(true){
            //synchronized后面加上this,代表锁住的是一个MyThread对象
            synchronized(this){
                //获取当前正在执行的线程的名字
                System.out.println(Thread.currentThread().getName()+"---"+ i);
                i--;
                Thread.yield();
                if(i<0){
                    break;
                }
            }
        }
    }
}

再来看看运行结果:

线程a---100
线程a---99
线程a---98
线程a---97
线程b---96
线程b---95
线程b---94
线程b---93
线程b---92
线程b---91
线程b---90
线程b---89
线程b---88
线程b---87
线程b---86
线程b---85
线程b---84
线程b---83
线程b---82

这时数据就不会丢失。

在这里需要强调的是,synchronized关键字锁住的不是花括号内的代码,而是MyThread的对象,在synchronized内代码没有结束时,同步锁不会释放,这时,即使其他线程抢占到CPU,因为它没有这把同步锁,所以不能执行该部分代码,只能等到同步锁释放后才能竞争。
5人推荐
随时随地看视频
慕课网APP