Thread线程介绍
线程简介
线程 是进程内的执行单元。
线程的基本操作
- 新建线程
Thread t1 = new Thread();
t1.start();
//t1.run();//不能启动线程
Thread t1 = new Thread(){
@Override
public void run() {
System.out.println("hello~ i am a new thread");
}
};
t1.start();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("i am a runnable thread");
}
});
t1.start();
- 停止线程
Thread.stop()
不建议使用该方法,因为他会释放所有的moitor,而且这个方法是不安全的,已经被废弃了的方法 - 中断线程
Thread.interrupt()//中断线程
Thread.isInterrupted()//判断是否被中断
public void run() {
while(true) {
Thread.yield();
}
}
t1.interrupt();
如上代码一个线程t1的run方法中实现了一个while循环,在main主线程中调用t1.interrupt()方法中断此线程,interrupt其实就是给在正在运行的线程中发一个中断指令,正常理解线程t1应该中断,但其实并没有,线程t1仅仅是收到了主线程发送的一个指令,或者说是打了一个招呼,但是收到指令后怎么去做,并没有给出,线程t1仍然会继续执行循环。
很优雅的处理线程中断,需修改如下:
public void run() {
while(true) {
if(Thread.currentThread().isInterrupted()) {
System.out.printli("t1 is interruted !")
break;
}
Thread.yield();
}
}
-
等待线程
Thread.sleep(long millis) throws InterruptedException
这个方法很熟悉,会是当前线程等待 指定的时间 去执行,但会有InterruptedException异常抛出,因为程序会认为当正在线程等待的时候,没有做其它任务的逻辑处理,此时发生线程中断,也应该立即中断此线程,而无需继续等待 -
线程挂起和继续执行
Thread.suspend(); 线程挂起
Thread.resume(); 继续执行
这两种线程操作方法都是不推荐使用的方法。
为什么不推荐使用了呢?
如果一个线程t1中使用了一个对象锁,然后因为某种操作t1需要挂起suspend操作,在另一个线程t2中去操作t1继续执行resume(),由于是多线程操作,某些情况下可能会导致t2线程中执行的t1.resume()会发生在t1的挂起操作suspend之前,由于resume被先于执行,t1线程就会无限被挂起,而此时如果t3线程需要用到线程t1中同一个对象锁时,由于t1线程挂起,锁还未释放,这也会导致t3线程无法获取锁,也无法继续执行,导致非常尴尬的情况发生。
public class SuspendTest {
public static Object u = new Object();
static ChangeObjectThread t1 = new ChangeObjectThread("t1");
static ChangeObjectThread t2 = new ChangeObjectThread("t2");
public static class ChangeObjectThread extends Thread {
public ChangeObjectThread(String name) {
super.setName(name);
}
@Override
public void run() {
synchronized(u) {
System.out.printli("in " + getName());
Thread.currentThread().suspend();
}
}
}
public static void main(String[] arg) throws InterruptedException {
t1.start();
Thread.sleep(100);
t2.start();
t1.resume();
t2.resume();
t1.join();
t2.join();
}
}
上述代码中,main方法无法正常结束。
- 等待线程结束(join)和 谦让(yeild)
yeild方法是指将自己所占用的CPU或资源释放掉,然后和其他线程资源重新抢占资源的一个方法,并不是放弃了自己所占有的资源,使用此方法也还是有可能使当前线程获取资源并往下执行,只是给了其他线程重新获取资源的机会。
join()方法是等待调用该方法的线程执行结束,会有一个阻塞主线程的感觉,多个线程的join()操作相当于在主线程的汇聚。
public class JoinMain {
public volatile static int i=0;
public static class AddThread extends Thread {
@Override
public void run() {
for(i=0;i<10000000;i++);
}
}
public static void main(String[] args) throws InterruptedException {
AddThread at=new AddThread();
at.start();
at.join();
System.out.println(i);
}
}
守护线程
在后台默默的完成一些系统性的服务,比如垃圾回收线程,JIT线程就可以理解为守护线程
当一个Java应用内,只有收回线程时,Java虚拟机就会自然退回出
Thread t=new DaemonT();
t.setDaemon(true);
t.start();
线程优先级
线程是可以设置优先级的,优先级高的线程更容易获取资源
Thread high=new HightPriority();
LowPriority low=new LowPriority();
high.setPriority(Thread.MAX_PRIORITY);
low.setPriority(Thread.MIN_PRIORITY);
low.start();
high.start();
基本线程同步操作
synchroinzed
- 指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。
public class AccountingSync implements Runnable {
static AccountingSync instance = new AccountingSync();
static int i=0;
@Override
public void run() {
for(int j=0; j<10000000; j++) {
synchronized(instance) {
i++;
}
}
}
public static void main(String[] arg) throws InterruptedException {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(i);
}
}
- 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。
public class AccountingSync implements Runnable {
static AccountingSync instance = new AccountingSync();
static int i=0;
public synchronized void increase() {
i++;
}
@Override
public void run() {
for(int j=0; j<10000000; j++) {
increase();
}
}
public static void main(String[] arg) throws InterruptedException {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(i);
}
}
- 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。
Object.wait() Object.notify()
wait是线程等待在当前对象上,
notify通知等待在当前对象的线程,使从wait状态返回
wait 和 notify 必须使用在获取当前对象锁(监视器)中使用
wait执行当前等待后,会释放当前对象的监视器,供其他线程使用。
-------T1 -------------------------------T2--------------------
取得object监视器
object.wait();
释放object监视器
-----------------------------------取得object监视器
-----------------------------------object.notify();
等待object监视器 -----------释放object监视器
重新获取object监视器
释放object监视器
public class SimpleWN {
final static Object obj = new Object();
public static class T1 extends Thread {
public void run() {
synchrioized(obj) {
System.out.println(System.currentTimeMillis() + ":T1 start !");
try {
System.out.println(System.currentTimeMills() + ":T1 wait for object");
obj.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currnetTimeMills() + ":T1 end !");
}
}
}
public static class T2 extends Thread {
public void run() {
synchrioized(obj) {
System.out.println(System.currentTimeMillis() + ":T2 start ! notify noe thread ");
obj.notify();
System.out.println(System.currentTimeMills() + ":T2 end!");
try {
Thread.sleep(2000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread();
Thread t2 = new Thread();
t1.start();
t2.start();
}
}