第十二章学习笔记

一,教材学习内容(12多线程机制)

1,进程与进程:线程不是进程,但线程的行为很像进程,线程是比进程更小的执行单位,一个进程在执行过程中,可以产生多个线程每个线程也有它自身产生,存在和消亡的过程。与进程不同的是,线程的中断和恢复可以更加节省系统的开销。

需要注意的是:没有进程就没有线程!

2,

Java的线程具有五中基本状态

新建状态(新):当线程对象对创建后,即进入了新建状态,如:线程t = new MyThread();

就绪状态(可运行): 当调用线程对象的开始()方法(t.start();),线程即进入就绪状态处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

运行状态(运行):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。

有四种原因可能引起中断:

1,JVM(Java虚拟机)将CPU资源从当前线程切换到其他线程,使本线程让出的使用权的CPU而处于阻塞状态。

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

2,线程使用CPU期间,使用睡眠()方法使当前线程处于休眠状态。

3,线程使用CPU期间,执行了等待()方法,使得当前想线程进入等待状态。等待状态的线程不会主动进入线程队列中排队等待CPU的资源,必须由其它线程调用通知()方法通知它,使它重新进到线程队列中排队等待CPU资源。

根据阻塞产生的原因不同,阻塞状态又可以分为三种:

1.等待阻塞:运行状态中的线程执行等待()方法,使本线程进入到等待阻塞状态;

2.同步阻塞 - 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

3.其他阻塞 - 通过调用线程的sleep()或join()或发出了I / O请求时,线程会进入到阻塞状态。当sleep()状态超时,join()等待线程终止或者超时,或者I / O处理完毕时,线程重新转入就绪状态。

死亡状态(死):线程执行完了或者因异常退出了的run()方法,该线程结束生命周期。

3,线程具有优先级

每一个Java线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。

Java线程的优先级是一个整数,其取值范围是1(Thread.MIN_PRIORITY) - 10(Thread.MAX_PRIORITY)。

默认情况下,每一个线程都会分配一个优先级NORM_PRIORITY(5)。

具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。

4,主题类与线程的创建

1)使用螺纹类或子类创建线程对象。

2)在编写线程类的子类时,需要重写父类的run()的方法,以规定线程的具体操作。

3)使用螺纹子类创建现场的优点是:可以在子类中增加新的成员变量,使线程具有某种属性,也可以在子类中新增加方法,使线程具有新的功能。

线程的创建:
1)使用Thread类进行创建

class MyThread extends Thread {
    
    private int i = 0;

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

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            if (i == 30) {
                Thread myThread1 = new MyThread();     // 创建一个新的线程  myThread1  此线程进入新建状态
                Thread myThread2 = new MyThread();     // 创建一个新的线程 myThread2 此线程进入新建状态
                myThread1.start();                     // 调用start()方法使得线程进入就绪状态
                myThread2.start();                     // 调用start()方法使得线程进入就绪状态
            }
        }
    }
}

2)实现可运行接口,并重写该接口的run()的方法,该运行()方法同样是线程执行体,创建可运行实现类的实例,并以此实例作为线程类的参数来创建主题对象,该线程对象才是真正的线程对象。

使用Runnable接口实现线程(Thread(Runnable target))调用run()方法的步骤次序与直接使用Thread类是一样的。这里的Thread对象类似于一个启动器。

class MyRunnable implements Runnable {
    private int i = 0;

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

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            if (i == 30) {
                Runnable myRunnable = new MyRunnable(); // 创建一个Runnable实现类的对象
                Thread thread1 = new Thread(myRunnable); // 将myRunnable作为Thread target创建新的线程
                Thread thread2 = new Thread(myRunnable);
                thread1.start(); // 调用start()方法使得线程进入就绪状态
                thread2.start();
            }
        }
    }
}

需要注意的是:不能对同一线程对象多次调用星()方法。

5,目标对象与线程的关系

1)目标对象与线程完全解耦

这里的完全解耦指的是目标对象不包括线程对象的引用

2)目标对象组合线程(弱耦合)

这里的弱耦合指的是线程对象组合目标对象。

6,线程常用的几个方法

1)星号()方法:启动线程,使之从新建状态进入就绪队列中排队,注意,每一个线程对象只能使用一次星()方法,不能多次调用

2)run()方法:用来定义线程对象被调度之后所执行的操作,需要用户重写。

3)sleep(int time)方法:线程休眠time毫秒,此方法可以完成一些特定的功能或者使高级别的线程休眠。

4)inAlive()方法:用于线程调用,返回boolean值,用以判断线程状态。

5)currentThread()方法:Thread类的类方法,可以返回当前正在使用cpu资源的线程。

6)interrupt()方法:用来吵醒被sleep()方法休眠的线程,使其重新排队等候cpu资源。

7、线程同步: java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 从而保证了该变量的唯一性和准确性。

保证线程运行顺序的正确性和安全性。

线程同步就是若干个线程都需要使用一个synchronize(同步)修饰的方法,即程序中若干个线程都需要使用一个方法,而这个方法用synchronize给予修饰。多个线程调用synchronize方法必须遵守同步机制。

同步机制:当一个线程A使用synchronize方法时,其他线程想使用这个synchronize方法时就必须等待,直到线程A使用完synchronize方法。

8、协调同步线程

当一个线程使用的同步方法中用到某个变量,而此变量又需要其他线程修改后才能符合本线程的需要,那么可以在同步方法中使用wait()方法。其他线程如果在使用这个同步方法时不需要等待,那么它使用完这个同步方法的同时,应该用notifyAll()方法通知所有由于使用这个同步方法而处于等待的线程结束等待,曾中断的线程就会从刚才中断处继续执行这个同步方法,并遵循“先中断先进行”的原则。如果使用notify()方法,那么只是通知处于等待中的一个线程等待结束。

wait()、notify()、notifyAll()方法都是Object类中的final方法,被所有类继承且不允许被重写。

特别注意:不可以在非同步方法中使用等待(),通知()和notifyAll的()方法。

9,线程联合

一个线程在占有CPU资源期间,可以让其他线程调用join()方法和本线程联合。

一旦线程甲联合线程B,那么甲线程将立刻中断执行,一直等到乙线程执行完毕,A线程再重新排队等待,以便恢复执行。如果一个准备联合的乙线程已经结束,那么B.join()将不会产生任何效果。

猜你喜欢

转载自blog.csdn.net/Huangxu_MIKU/article/details/84700361
今日推荐