转载

实战java高并发程序设计第二章

1.线程的基本状态 
 2.线程的基本操作 
 3. volatile与java内存模型 
 4.线程组 
 5.守护线程(Daemon) 
 6.线程优先级 
 7.线程安全与synchronized 
 8.隐蔽错误

1.线程的基本状态

  1. 线程的生命周期

实战java高并发程序设计第二章

2.线程的基本操作

1.新建线程

Thread tl=new Thread(){
        @override
        public void run(){
            System.out.println("Hel1o,I am t1");
        };
        t1.start();
    t1.start();

2.终止线程

Thread.stop()    //立即终止线程所有活动

stop()方法在结束线程时,会直接终止线程,并立即释放这个线程所持有的锁,可能引起数据不一致,强烈建议不使用!!

//正确停止线程的方法
    public static class ChangeObjectThread extends Thread {
        volatile boolean stopme = false;     //标记位,记录是否要停止线程
        
        public void stopMe(){
            stopme = true;
        }
        @Override
        public void run() {
            while (true) {
                if (stopme){                //在合适的地方停止线程,避免数据不一致
                    System.out.println("exit by stop me");
                    break;
                }
                synchronized (u) {
                    int v = (int) (System.currentTimeMillis() / 1000);
                    u.setId(v);
                    //Oh, do sth. else
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    u.setName(String.valueOf(v));
                }
                Thread.yield();
            }
        }
    }

3.线程中断

public void Thread.interrupt()        //中断线程,仅发送通知,设置标记位,等待合适时机线程中断
public boolean Thread.isInterrupted()    //判断是否被中断,判断标记位
public static boolean Thread.interrupted()//判断是否被中断,并清除当前中断状态
Thread tl=new Thread(){
    @Override
    public void run(){
        while(true){
            if(Thread.currentThread().isInterrupted()){    //需要设立中断处理方法,否则无法响应中断
                System.out.println("Interruted!");
                break;
            )
            Thread.yield();
}
public class InterruputSleepThread {
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(){
            @Override
            public void run(){
                while(true){
                    if(Thread.currentThread().isInterrupted()){
                        System.out.println("Interruted!");
                        break;
                    }
                    try {
                        Thread.sleep(2000);            //由于中断而抛出异常会清除中断标记
                    } catch (InterruptedException e) {
                        System.out.println("Interruted When Sleep");    //sleep被中断后,重置标记位继续运行,保证数据一致性和完整性
                        //设置中断状态
                        Thread.currentThread().interrupt();
                    }
                    Thread.yield();
                }
            }
        };
        t1.start();
        Thread.sleep(2000);
        t1.interrupt();
    }
}

4.等待(wait)和通知(notify)

public final void wait() throws InterruptedException;
public final native void notify();

object.wait()和object.notify()方法必须包含在 synchronized 关键字中,因为要获取对象的监视器(monitor对象)

public class SimpleWN {
    final static Object object = new Object();
    public static class T1 extends Thread{
        public void run()
        {
            synchronized (object) {
                System.out.println(System.currentTimeMillis()+":T1 start! ");
                try {
                    System.out.println(System.currentTimeMillis()+":T1 wait for object ");
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(System.currentTimeMillis()+":T1 end!");
            }
        }
    }
    public static class T2 extends Thread{
        public void run()
        {
            synchronized (object) {
                System.out.println(System.currentTimeMillis()+":T2 start! notify one thread");
                object.notify();
                System.out.println(System.currentTimeMillis()+":T2 end!");
                try {
                    Thread.sleep(2000);        //此处sleep()2秒,T1此时仍然需要等待2秒才会继续执行
                } catch (InterruptedException e) {
                }
            }
        }
    }
    public static void main(String[] args) {
        Thread t1 = new T1() ;
        Thread t2 = new T2() ;
        t1.start();
        t2.start();
        //输出:
        //1565249714094:T1 start! 
        //1565249714094:T1 wait for object 
        //1565249714094:T2 start! notify one thread
        //1565249714094:T2 end!
        //1565249716094:T1 end!
    }
}
wait()和sleep()的区别:
1.wait必须在同步条件内使用,sleep无此要求
2.wait释放锁,sleep不会释放
3.wait为Object内的实例方法,sleep为Thread的静态方法
4.wait需要调用对象的notify方法唤醒,sleep知道时间结束或者被interrupt打断

5.挂起(suspend)和继续执行(resume)

废弃方法,不作介绍!!有需求可使用wait和notify

6.等待线程结束(join)和谦让yield

public final void join() throws InterruptedException    //一直阻塞线程直至结束
public final synchronized vold join(long millis)throws InterruptedException    //给出最大等待时间

join的机制实际为在方法调用线程循环wait,如下join()核心代码:

while(isAlive()){
    wait(0);
}
public static native void yield();

yield()方法表示当前线程让出cpu计算资源,但还是会参与cpu资源的争夺,一般用于防止低优先级线程占用太多cpu资源

3. volatile与java内存模型

volatile关键字可以保证一定的原子性,但是不能替代锁,不能保证100%线程安全
volatile可以保证可见性和有序性,充当内存栅栏,禁止指令重拍

4.线程组

当一个系统中线程较多且功能分配比较明确是可以使用线程组
public class ThreadGroupName implements Runnable {
    public static void main(String[] args) {
        ThreadGroup tg = new ThreadGroup("PrintGroup");
        Thread t1 = new Thread(tg, new ThreadGroupName(), "T1");
        Thread t2 = new Thread(tg, new ThreadGroupName(), "T2");
        t1.start();
        t2.start();
        System.out.println(tg.activeCount());    //2
        tg.list();        //java.lang.ThreadGroup[name=PrintGroup,maxpri=10]
                          //    Thread[T1,5,PrintGroup]
                          //    Thread[T2,5,PrintGroup]
    }
    @Override
    public void run() {
        String groupAndName = Thread.currentThread().getThreadGroup().getName()
                + "-" + Thread.currentThread().getName();
        while (true) {
            System.out.println("I am " + groupAndName);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

activeCount()获取线程组中的活动线程数

list()则打印线程组中的所有线程信息

5.守护线程(Daemon)

守护线程在后台执行,如垃圾回收线程,与之对应的为用户线程,当守护线程要守护的对象不存在了,则守护线程自动退出

当一个java应用中只有守护线程时,java虚拟机自动退出

public class DaemonDemo {
    public static class DaemonT extends Thread{
        public void run(){
            while(true){
                System.out.println("I am alive");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t=new DaemonT();
        t.setDaemon(true);    //此方法必须在start方法前
        t.start();
        
        Thread.sleep(2000);
    }
}

上述代码中 t被设置为守护线程,当主线程退出时,守护线程也会退出;若未设置为守护线程,主线程退出后,t线程将依旧打印.

6.线程优先级

线程可以设置优先级,优先级高的线程获取到cpu资源的概率会更大(但不是一定会比低优先级的线程先获取到cpu资源)
public class PriorityDemo {
    public static class HightPriority extends Thread{
        static int count=0;
        public void run(){
            while(true){
                synchronized(PriorityDemo.class){       //此处锁住该类是为了让产生一次资源竞争,使优先级差异表现更为明显
                    count++;
                    if(count>10000000){
                        System.out.println("HightPriority is complete");
                        break;
                    }
                }
            }
        }
    }
    public static class LowPriority extends Thread{
        static int count=0;
        public void run(){
            while(true){
                synchronized(PriorityDemo.class){
                    count++;
                    if(count>10000000){
                        System.out.println("LowPriority is complete");
                        break;
                    }
                }
            }
        }
    }
    /**
     * HightPriority先完成的次数多,但是 不保证
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Thread high=new HightPriority();
        LowPriority low=new LowPriority();
        high.setPriority(Thread.MAX_PRIORITY);    //此方法可以设置优先级 0-10 数字
        low.setPriority(Thread.MIN_PRIORITY);
        low.start();
        high.start();
    }
}
试验多次HightPriority总是能比LowPriority快,但是不保证一定是这样.

7.线程安全与synchronized

synchronized为重量级同步锁,实现线程间的同步,sychronize锁住的对象、方法和代码块,每一次只能有一个线程进行访问,从而保证了线程的安全

    用法:
    
指定锁对象: synchronized(object){.....}
指定实例方法 : public  synchronized void println()
指定静态方法: public static synchronized void println()
public class BadAccountingSync2 implements Runnable{
    static int i=0;
    public static synchronized void increase(){        //此处如果不适用static则为线程不安全,最终i值必定小于20000
        i++;
    }
    @Override
    public void run() {
        for(int j=0;j<10000;j++){
            increase();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(new BadAccountingSync2());
        Thread t2=new Thread(new BadAccountingSync2());
        t1.start();t2.start();
        t1.join();t2.join();
        System.out.println(i);     //输出20000
    }
}

8.隐蔽错误

待续.......

原文  https://segmentfault.com/a/1190000020011725
正文到此结束
Loading...