进程线程的概念
进程是建立在操作系统的一次运行活动,是系统进行资源分配和调度的基本单位,可理解为一个一个的程序。线程是一次指令的顺序执行,是系统独立和分配CPU的基本单位,可理解为进程中独立运行的子任务。
为什么引入多线程
同步单线程环境下,使得不相关、相互独立的任务之间需要排队等候CPU,使得CPU的利用率低下,异步引入多线程使得不同的任务能在CPU自如地切换,提高了CPU的利用率。
线程实现方式
实现Runnable接口和继承Thread,并实现run()方法(一般使用Runnable接口实现,原因:接口能够实现多继承,类只能单继承)。
注:在主函数中多次调用start()会出现Exception in thread "main" java.lang.IllegalThreadStateException
多线程环境下,在主函数直接调用Thread.run()方法而非调用Thread.start(),则实现的是同步效果,而非异步执行
线程方法
线程生命周期交互图
isAlive():测试线程是否处于活跃状态。
getId():线程的唯一标识号。
yield():放弃当前CPU让其他任务占用CPU,但放弃时间不确定。有可能刚放弃又占用。
sleep()/interrupt,wait()/notify notifyAll:
调用sleep()方法不会释放锁(不让出系统资源),而wait方法释放了锁(进入线程等待池等待,让出系统资源)使得其他线程可以使用同步控制块或者方法,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行终止。
suspend/resume:
如果使用不当, 极易造成公共的同步对象的独占, 使得其他的线程无法访问公共的同步对象。
public class ThreadSuspendTest {
    public synchronized void printString(){
        System.out.println("begin");
        if(Thread.currentThread().getName().equals("a")){
            System.out.println("Thread a will suspend");
            Thread.currentThread().suspend();
        }
        System.out.println("end");
    }
    public static void main(String[] args){
        try{
            final ThreadSuspendTest threadSuspendTest = new ThreadSuspendTest();
            Thread thread1 = new Thread(new Runnable() {
                public void run() {
                    threadSuspendTest.printString();
                }
            });
            thread1.setName("a");
            thread1.start();
            Thread thread2 = new Thread(new Runnable() {
                public void run() {
                    System.out.println("B线程启动了, 但是无法进入printString方法中");
                    System.out.println("因为printString()方法陪线程a锁定并且永远suspend暂停了");
                    threadSuspendTest.printString();
                }
            });
            thread2.setName("B");
            thread2.start();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
/*begin
Thread a will suspend
B线程启动了, 但是无法进入printString方法中
因为printString()方法陪线程a锁定并且永远suspend暂停了*/
停止线程的方法
ThreadDeath
实例变量的安全问题
- 
(1)实例变量
 - (2)同一实例访问static时发生线程安全问题
 - (3)system.out.println(i++);与i++/i--..联合使用异常
 
this.getName与currentThread().getName()区别
class CountOperate extends Thread {
    public CountOperate() {
        System.out.println("CountOperate---begin");
        System.out.println("Thread.currentThread().getName()=" + Thread.currentThread().getName());
        System.out.println("this.getName()=" + this.getName());
        System.out.println("CountOperate---end");
    }
    @Override
    public void run() {
        System.out.println("run---begin");
        System.out.println("Thread.currentThread().getName()=" + Thread.currentThread().getName());
        System.out.println("this.getName()=" + this.getName());
        System.out.println("run---end");
    }
}
public class Run3_getName {
    public static void main(String[] args) {
        CountOperate c = new CountOperate();
        Thread t1 = new Thread(c);
        t1.setName("A");
        t1.start();
    }
}
输出:
CountOperate---begin
Thread.currentThread().getName()=main
this.getName()=Thread-0
CountOperate---end
run---begin
Thread.currentThread().getName()=A
this.getName()=Thread-0
run---end
守护线程
守护线程











网友评论