j2se学习中的一些零碎知识点8

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了j2se学习中的一些零碎知识点8相关的知识,希望对你有一定的参考价值。

1、多线程的基本概念:

-  线程是指进程中的一个执行场景,也就是执行流程。(每个进程就是一个应用程序,都有独立的内存空间;同一个进程中的线程共享其进程中的内存和资源。)

-  多进程的作用:单进程使计算机只能够做一件事情。(如windows中的dos窗口命令行。)对于单核计算机,在同一时间点上,计算机的CPU只能够做一件事情,由于计算机在进程和进程之间频繁的进行切换,且切换速度极高,使人感觉多个进程在同时运行。(多进程的作用不是提高执行速度,而是为了提高CPU的使用率。)

-  需要注意,进程与进程之间的内存是独立的。

-  线程是一个进程中的执行场景,一个进程可以启动多个线程。多线程的作用:多线程不是为了提高执行速度,而是提高应用程序的使用率。由于计算机的执行速度非常快,可以给现实世界的人产生一种错觉,即多个线程在同时并发运行。(需要注意,java中的线程和线程共享“堆内存和方法区内存”,栈内存是独立的,一个线程一个栈。)


5、java程序的运行原理?

-  java命令会启动java虚拟机,启动JVM,等于启动了一个应用程序,表示启动了一个进程。该进程会自动启动一个“主线程”,然后主线程去调用某个类的main方法。所以main方法运行在主线程中。如果没有启动其他线程,那就只有一个主线程在运行。

技术分享


6、线程的定义、创建和启动:(第一种方式)

-  java.lang.Thread类实现了java.lang.Runnable接口,Runnable接口中声明了run方法,Thread类中的run方法定义为:

技术分享

-  run()方法在API文档中的说明:自定义的线程构造后会调用重写的run方法:(所以在自定义线程类时,需要继承Thread类,并重写Thread类中的run()方法)

技术分享




-  构造器Thread()方法创建一个线程,自定义的线程可以使用默认的构造器创建线程,默认的构造器在执行的第一行中会调用父类即Thread类的默认的构造器:

技术分享


-  java.lang.Thread类中的start()方法的调用将使此线程开始执行,java虚拟机会调用此线程中的run()方法:

技术分享


-  示例代码:(需要注意的是,有了多线程之后,main方法结束只是主线程中没有方法栈帧,但是其他线程或者其他栈中还有栈帧,所以main方法结束,程序可能还在运行。)

技术分享


-  线程交叉运行:

技术分享


7、实现线程可以有第二种方式(自定义类实现java.lang.Runnable接口,并实现run()方法,比起自定义类直接继承Thread类来说,这种方式比较推荐,因为这个类实现接口之外保留了类的继承。)

-  构造器Thread(Runnable target)方法可以传递Runnable类型的对象创建线程:

技术分享


-  示例代码:

技术分享


8、关于线程的生命周期:(状态图)

技术分享


-  解释上例ThreadTest03示例代码中线程生命周期的状态:首先java命令启动java虚拟机,java虚拟机的启动表示开启了一个应用程序(即进程),该进程会自动开启一个“主线程”,然后这个主线程会调用ThreadTest03类中的main方法,在方法中使用new关键字创建了t线程(新建状态),线程创建后调用start方法进入就绪状态,这个时候主线程和t线程一起同时抢夺CPU的时间片(时间片中的时间可长可短),首先抢夺到时间片的线程由java虚拟机调度自动运行run方法,当线程中时间片中的时间段结束时另一个线程中自动运行run方法。两个线程的时间片都结束后,两个线程又会重新会到就绪状态重新抢夺时间片,首先抢夺到时间片的线程继续执行run方法(接着执行,而不是重新执行),直到run方法运行结束线程消亡。期间可能发生阻塞事件导致线程进入阻塞状态,当阻塞解除时线程又会重新返回到就需状态。


9、线程的调度与控制:

-  通常我们的计算即只有一个CPU,CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。在单CPU的机器上线程不是并行运行的,只有在多个CPU上线程才可以并行运行。Java虚拟机要负责线程的调度,取得CPU的使用权,目前有两种调度模式:分时调度模型和抢占式调度模型,Java使用抢占式调度模型。

-  分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片。

-  抢占式调度模型:优先级高的线程获取的CPU时间片相对会多一些。如果线程的优先级相同,那么会随机选择一个。

-  线程的优先级主要分为三种:Thread类中有三个常量,MAX_PRIORITY(10、最高级)、MIN_PRIORITY(1、最低级)和NORM_PRIORITY(5、默认)。


-  java.lang.Thread类中的currentThread()方法返回的是当前正在执行的线程对象:

技术分享


-  java.lang.Thread类中的getName()方法返回的是线程对象的名字:(主线程默认的名字是main,其他线程的名字为Thread-编号)

技术分享


-  java.lang.Thread类中的setName(String name)方法设置线程对象的名字:


技术分享


-  java.lang.Thread类中可以通过getPriority()和setPriority(int newPriority)方法获取和设置线程优先级:

技术分享

技术分享


10、关于sleep方法(线程休眠方法):Thread.sleep(毫秒),该方法的作用:阻塞当前线程,腾出CPU,让给其他线程。(进入阻塞状态)

技术分享


-  面试题:

技术分享


-  某线程正在休眠,如何打断它的休眠:(第一种方式)

-  java.lang.Thread类中的interrupt()方法打断线程对象的休眠:

技术分享


-  示例代码:

技术分享



-  中止当前线程的第二种方式:

技术分享


10、yield方法和线程合并:

- java.lang.Thread类的静态yield()方法:会给同一个优先级的线程让位,但是让位时间不固定。和sleep方法相同,就是yield时间不固定。(yield是让位的意思)

技术分享


-  java.io.Thread类中的join()方法表示合并线程,等待指定线程对象死亡后再执行在线程环境中的的代码:

技术分享


-  示例代码:

技术分享


12、线程的同步:

-  异步编程模型和同步编程模型的区别?

有两个线程t1和t2需要执行,t1线程执行t1,t2线程执行t2的,两个线程之间谁也不等谁,这是异步编程模型。t1线程和t2线程执行,当t1线程必须等t2线程执行结束之后,t1线程才能执行,这是同步线程模型。

-  线程同步是为了数据安全,尽管应用程序的使用率降低,但是为了保证数据是安全的,必须加入线程同步机制。(线程同步机制使得程序变成【等同于】单线程)

-  什么条件要使用线程同步?

1、必须是多线程环境;2、多线程环境共享同一个数据;3、共享的数据涉及到修改操作。


-  线程同步中的锁机制:(示例代码)

技术分享


-  以上代码中的synchronized同步语句块原理解析:有t1线程和t2线程,t1线程执行到此处,遇到了synchronized关键字,就会去找this的对象锁,如果找到了this的对象锁,则进入同步语句块中执行程序,当同步语句块中的代码执行结束之后,t1线程归还this的对象锁。

在t1线程执行同步语句块的过程中,如果t2线程也过来执行同步语句块中的代码,也会遇到synchronized关键字,所以也会去找this的对象锁,但是该对象锁被t1线程所持有,只能等待this对象锁的归还。(需要注意的是,synchronized关键字添加到成员方法上,线程拿到的也是this的对象锁。)

-  需要注意的是,使用synchronized同步语句块的方式实现线程同步控制的代码越精细越好,因为单线程的执行程序比较消耗时间。


-  面试题:

技术分享


-  类锁:示例代码

技术分享


-  死锁:示例代码

技术分享


-  线程分类可以分为两种:用户线程(以上讲的都是用户线程),和守护线程。守护线程是这样的,所有的用户线程结束生命周期,守护线程才会结束生命周期,只要有一个用户线程存在,那么守护线程就不会结束。例如java中著名的垃圾回收器就是一个守护线程,只有应用程序中所有的线程结束,它才会结束。(守护线程一般是无限执行的,除非其他所有的用户线程结束。)


-  java.lang.Thread类中的setDaemon(boolean on)方法标记当前的线程是作为一个用户线程还是守护线程。(该方法必须在线程调用start()方法之前被激活才有效。参数如果是true,则表示把当前线程设置为守护线程。)

技术分享

13、Timer定时器:java.util.Timer

-  构造器Timer()方法创建一个定时器:

技术分享


-  Timer类中的schedule(TimerTask task, Date firstTime, long period)方法指定定时任务:

技术分享

-  示例代码:

技术分享


14、Object类中的wait()方法和notify()方法:

-  导致当前线程等待,直到对象调用notify()或者是notifyAll()方法将该线程激活:

技术分享


-  唤醒单个线程,这个线程在对象监视器上等待:

技术分享


以上是关于j2se学习中的一些零碎知识点8的主要内容,如果未能解决你的问题,请参考以下文章

j2se学习中的一些零碎知识点5

j2se学习中的一些零碎知识点6

j2se学习中的一些零碎知识点2

j2se学习中的一些零碎知识点7

j2se学习中的一些零碎知识点9

j2se学习中的一些零碎知识点1(内容有些零散)