1.线程创建之后就具备了运行的条件,但是此时仅仅只是占有了内存资源,在JVM管理的线程中还没有该线程,
该线程必须调用start()方法通知JVM,这样JVM就知道又有一个新的线程排队等候切换了。
即:start()方法将线程加入线程队列中。
2.当JVM切换执行该线程时,run()方法就会被执行。
3.线程没有结束run()方法前,不要让线程调用start()方法,否则会报异常。
4.线程的创建:
线程的两种创建方式:继承Thread类和实现Runnable接口
1.继承Thread类的步骤:
a.继承Thread类,并重写run()方法
b.然后实例化
c.调用start()方法启动线程
=========Thread类已经实现了Runnable接口
2.实现Runnable接口的步骤:
a.实现Runnable接口,并重写run()方法
b.然后实例化
c.将实例化后的对象作为Thread类的构造方法的参数创建线程
d.然后调用start()方法启动线程
=========================
线程默认命名:主线程:main
用户自开启的多个线程依次使用:Thread-0,Thread-1...来命名.
5.获取或者设置线程的一些基本信息:获取id,优先级,名称,是否为守护线程等.
线程默认优先级为5,优先级越高抢占到CPU的几率越高.
获取主线程对象实例:Thread main = Thread.currentThread();
设置:使用set()方法设置线程的名称,设置线程的优先级,以及设置线程为守护线程,还可以使用构造方法设置
线程的名称,设置操作要在start()之前,否则会报错!
6.守护线程:是一个相对的感念,必须至少有两根线程,线程A依赖于线程B的存在,那么A就是守护线程,
相当于保镖和主人的关系,保镖就是守护线程。
当被守护线程B线程结束时守护线程A也会强制结束。
7.sleep(毫秒):静态方法,线程的休眠 -- 用来调试错误,暂停当前正在执行的线程。
1.在哪个线程里面调用sleep方法,哪个线程就会休眠,和调用者没有关系,因为该方法为静态方法。
2.局部内部类调用外部变量,改变量必须被final修饰
3.线程中不能跨线程抛异常,后者要try-catch
由于sleep()方法的使用具有迷惑性,所以不建议使用,而是使用TimeUnit.SECONDS.sleep(3);方法来替代。
8.两种创建方式的选择:
1.创建线程建议实现
2.继承Thread是在需要重写Thread方法时
大多数情况下,如果只想重写 run() 方法,而不重写其他 Thread 方法,那么应使用 Runnable 接口。
这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应为该类创建子类。
-------------------------------------------------------------------------------
9.线程的生命周期:
创建(new) --- 就绪(start) --- 运行(run) --- 阻塞状态 --- 死亡(run方法执行完毕)
线程从运行状态进入到阻塞状态的原因有以下几种:
1.等待同步锁 --- 获得同步锁
2.调用IO阻塞方法 --- 阻塞IO方法返回
3.wait() --- 调用notify()或者notifyAll()方法
4.其他线程调用join() --- 调用join()方法的线程终止执行
5.sleep() --- 睡眠时间到
------------------------------------------------------------------------------
线程死亡的2个原因:
1.正常死亡 -- run方法执行完毕
2.强制死亡 -- 被提前强制性终止
10.终止线程的方式:
1.标记法
2.stop
3.interrupt
什么时候需要使用interrupted?
1.线程休眠的时间过长
2.线程处于等待状态
3.线程被IO阻塞了
使用interrupted中断线程的时候会抛出异常,
在Interrupted之前,终止线程使用stop,但此方法已经被废弃了,
因为stop会导致死锁。