一,线程的概念:进程中的独立控制单元,线程控制着进程的执行;一个进程至少有一个线程。注:Java虚拟机启动时不止一个线程,还有垃圾回收线程
二,线程的创建:
1. 继承Thread类,重写Run()方法
线程的启动:
class MyThread extends Thread {
publicvoid run() {
// 线程执行的操作
}
}
new MyThread().start();
2. 实现Runnable接口,重写Run()方法(推荐使用,避免了Java的单继承局限性)
线程的启动:
Class MyThread implements Runnable{
publicvoid run() {
// 线程执行的操作
}
}
new Thread(new MyThread()).start();
三,多线程的安全问题:
原因:当多条语句同时被多个线程执行,某一个线程在执行了部分代码却没有执行完的时候另一个线程也参与进来执行,导致共享数据错误
解决方式:1.同步代码块
Synchronized(对象){
//需要被同步的代码
}
2同步函数(同步函数的锁是this,静态同步函数的锁是Class对象)
Public Synchronizedvoid test(){
}
注:同步的前提:1.必须要有两个或两个以上线程在运行;2.多线程必须使用同一个锁
同步的优缺点:优点:保证的共享数据的安全;缺点:降低了程序的运行效率(所以尽量减少使用同步)
JDK1.5中提供了多线程升级解决方案:
将同步替换成Lock操作,将notify(), notifyAll(), wait()替换成了Condition对象(通过Lock获取)
四,死锁:
原因:同步代码块代码块或函数中嵌套同步,并且两个同步的锁不相同
示例代码:
public class Test3 {
public static void main(String[] args) {
DeadLock td1 = new DeadLock();
DeadLock td2 = new DeadLock();
td1.flag = 1;
td2.flag = 0;
new Thread(td1).start();
new Thread(td2).start();
}
}
class DeadLock implements Runnable {
public int flag = 1;
static Object o1 = new Object(), o2 = new Object();
@Override
public void run() {
System.out.println("flag=" + flag);
if (flag == 1) {
synchronized (o1) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o2) {
System.out.println("1");
}
}
}
if (flag == 0) {
synchronized (o2) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (o1) {
System.out.println("0");
}
}
}
}
}
五,线程的生命周期
六,线程常用方法:
currentThread()
返回对当前正在执行的线程对象的引用
getName()
返回该线程的名称
getPriority()
返回线程的优先级。
getState()
返回该线程的状态。
interrupt()
中断线程。
interrupted()
测试当前线程是否已经中断。
isDaemon()
测试该线程是否为守护线程
run()
如果该线程是使用独立的Runnable
运行对象构造的,则调用该Runnable
对象的run
方法;否则,该方法不执行任何操作并返回。
setName(String name)
改变线程名称,使之与参数name
相同。
setPriority(int newPriority)
更改线程的优先级。
sleep(long millis)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
start()
使该线程开始执行;Java 虚拟机调用该线程的run
方法。
toString()
返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
yield()
暂停当前正在执行的线程对象,并执行其他线程。
七,notify(),notifyAll(),wait():
都使用在同步代码块中,因为要对持有监视器(锁)的线程操作,只有同步才有锁
注:等待和唤醒必须是同一个锁
八,线程的中断和恢复:
中断:线程在调用 Object 类的 wait()、wait(long)或 wait(long,int) 方法,或者该类的join()、join(long)、join(long,int)、sleep(long)或 sleep(long,int) 方法过程中受阻
恢复:线程调用interrupt()方法
九,守护线程:依赖非守护线程存在,当非守护线程结束以后,守护线程自动结束,可以通过setDaemon(true)将线程设为守护线程