1.java.lang.Thread
线程,一个程序内部的顺序控制流(JVM启动时有一个由主方法main所定义的线程)
1)通过创建Thread实例来创建新的线程;
2)每个线程通过某个特定Thread对象所对应的run()(成为线程题)来完成操作;
3)通过调用Thread类的start()来启动线程
2.与进程的区别?
1)每个进程有独立的代码和数据空间,进程间切换需要较大的开销;
2)线程可以看成轻量级的进程,同一线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器
3)多进程:在操作系统中能同时运行多个任务(程序)
4)多线程:在同一个应用程序中有多个顺序同时进行
3.线程控制基本方法
方法
|
功能
|
isAlive()
|
是否还活着,即线程是否还未终止
|
getPriority()
|
获得线程优先级(1《《10,默认5)
|
setPriority()
|
设置线程优先级()
|
Thread.sleep() [静态方法]
|
将当前线程睡眠指定毫秒数
|
join()
|
调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,在恢复执行
|
wait()
|
当前线程进入对象的wait pool
|
notify()/notifyAll()
|
唤醒对象wait pool中的一个/所有等待线程
|
yield
|
让出cpu,给其他线程并执行的机会
|
4.线程同步(synchronized)
Java引入对象互锁的概论,保证共享数据操作的完整性。每个对象都对应一个可称为“互斥锁”的标记,这个标记保证任一时刻只有一个线程访问该对象。
5.如何创建和启动一个线程?
方法一:
继承Thread类: 继承Thread类并覆盖其run()方法(较简洁,但不能继承其他类了)
TestThread_extend myThread = new TestThread_extend();
myThread.start();
方法二:
实现Runnable接口: 实现Runnable接口并实现其中唯一的run(),(由于Runnable接口对线程没有任何支持,在获得线程的实例时,只能通过Thread的构造函数Thread(Runnable target )来实现)
TestThread_implment myThread = new TestThread_implment();
Thread t = new Thread(myThread);//要通过Thread构造方法,实现实例化
6.线程的基本状态有哪些?他们之间有何关系?
1)New(新建)——当线程对象创建成功,且没有调用 start()方法
2)Runnable(可运行)——当start()时,线程首先进入可运行状态
3)Running(运行态)——线程调度程序从“可运行”池中选择一个线程,进入运行状的唯一方法。
4)Blocked(阻塞态)——当线程遇到异常、sleep、wait等操作所处的一种状态。
5)Dead(死亡态)——在此状态线程也许是活的,但已经不是一个可执行线程
PS:stop()和destroy()也会使线程处于死亡状态,当不被推荐。
stop()产生异常,destroy()强制终止,不会释放线程锁。线程一旦死亡,就不能复生
7.后台线程
调用start之前调用setDaemon(),可设置为后台线程。
8.如何使正在运行的线程只指定时间内休眠?
可以通过Thread.sleep(2000)(不建议“对象.sleep()”)使线程休眠一段时间,将系统资源让给其他线程程序
9.如何终止一个正在运行的线程?
可以使用Thread类中的一个intrerrupt()方法设置,使用Thread.isInterrupted()便可实现终止。
注:通常安全终止,都采用一个标志位控制run()的正常结束,而不是用Thread的方法。
10.为何stop()和suspend()方法不推荐?
stop(),暴力停止,没有做任何清楚操作,释放该线程已经锁定的所有监视器,如果以前受这些监视器保护的任何对象都处于一种不连贯状态,那么损坏的对象对其他线程可见,可能导致不安全操作。
【应置入标志控制目标线程是“活动”还是“停止”】如果停止运行,则正常结束run(),如果目标线程等待时间过长,则应该使用inperrupt()中断该等待。
suspend(),已遭到反对,具有固有的死锁倾向。
【应置入标志控制目标线程是“活动”还是“挂起”】如果应该挂起,则用wait()进入等待状态,用notify恢复。
11.如何控制线程的暂停和启动?
方法一:sleep()
使线程进入阻塞状态,休眠过后,重新进入等待状态。不会立刻执行,而是等待(时间不定)。
如果对一个正在sleeping的线程使用interrupt()中断时将会抛出InterruptedException异常。
用例:Thread.sleep();
方法二:wait()和notify()
匹配使用,wait()进入阻塞状态有2方法,一种指定毫秒(notify()调用或者时间到),一种没有参数(必须notify()调用)。
thread1.wait() / thread1.notify
方法三:yield()
使正在运行的线程放弃当前分配的CPU时间,但不会使线程堵塞,即线程仍处于可执行状态,随时可能再次得到CPU时间。
方法四:join()
表示等待该线程执行完毕再调度其他线程(可有时间参数,等待该线程终止的最长时间),如果另一个线程中断该线程,会抛出InterruptedException。
12.如何实现多个线程同步?
A_Java内置语音级的同步原语synchronized关键字,实现对共享资源的同步访问。
1)同步方法
public synchronized void method() {}
同步加锁的是“对象”而不是“代码”。因此,如果在一个类中有一个同步方法,该方法是可以被两个线程“同时”执行的,只要每个线程自己创建一个该类的实例即可。
public synchronized void printVal(int v) {
for(int i = 0; i < 100; i++) {
System.out.print(v);
}
}
以上锁定的是对象而非代码块,如果需要实现真正的同步,必须同步一个全局对象或者对“类”同步。同步类如下:
public void printVal(int v) {
synchronized (TestSynMothod.class) {
for(int i = 0; i < 100; i++) {
System.out.print(v);
}
}
}
2)同步公共的静态成员变量
基于线程同步的一般原理是应该尽量减小同步的粒度,针对上文实例,可以通过公共对象加锁,既添加一个静态成员变量来实现。
private static Object lock = new Object();
3)同步游离块
与同步公共的静态成员变量类似,都为减低同步粒度。
synchronized{ // do something }
4)同步静态方法
获得的锁是Object对象
public synchronized static void printVal(int v) {
for(int i = 0; i < 100; i++) {
System.out.print(v);
}
}
B_Metux互斥体的设计和使用
C_ThreadLocal互斥体的设计和使用
阅读(2121) | 评论(0) | 转发(0) |