1. 程式人生 > >Java併發程式設計學習(一)——標準Thread

Java併發程式設計學習(一)——標準Thread

1、雖然System.out.println內部是加了鎖的,但是如果System.out.println(i- -),依然是執行緒不安全的,因為有的JVM,i- -需要三步才能完成。

2、通過interrupt方法停止執行緒

public class IntteruptStop
{
    public static void main(String[] args)
    {
        try
        {
            MyThread mt = new MyThread();
            mt.start();
            Thread.sleep(1000
); mt.interrupt(); } catch(Exception e) { } } private static class MyThread extends Thread { @Override public void run() { for(int i = 0; i < 500000; i++) { System.out.println("i = "
+ (i + 1)); //這裡也可以用Thread.interrupted(); if(currentThread().isInterrupted()) { System.out.println("break"); break; } } //注意,如果這裡還有程式碼,依然會繼續執行 } } }

3、interrupted方法會清除狀態標誌,而isInterrupted不會

4、interrupted方法和sleep

public class InterruptSleep
{
    public static void main(String[] args)
    {
        try
        {
            MyThread mt = new MyThread();
            mt.start();
            Thread.sleep(1000);
            mt.interrupt();
        }
        catch(Exception e)
        {

        }

    }

    private static class MyThread extends Thread
    {
        @Override
        public void run()
        {
//          for(int i = 0; i < 500000; i++)
//          {
//              System.out.println("i = " + (i + 1));
//          }
            try
            {
                System.out.println(System.currentTimeMillis());
                Thread.sleep(5000);
            }
            catch(InterruptedException e)
            {
                System.out.println(System.currentTimeMillis());
                System.out.println("end");
                //這裡標誌已經被清除成false
                System.out.println(isInterrupted());
            }

        }
    }
}

可以理解為sleep方法會時刻檢查isInterrupt的值,如果為true就會立刻結束並丟擲異常,同時把標誌清為false。

5、不要使用stop方法

public class StopError
{
    public static void main(String[] args)
    {
        try
        {
            SynchronizedObject obj = new SynchronizedObject();
            MyThread mt = new MyThread(obj);
            mt.start();
            Thread.sleep(500);
            mt.stop();
            System.out.println(obj.getUsername() + ", " + obj.getPassword());
        }
        catch(Exception e)
        {

        }
    }

    private static class SynchronizedObject
    {
        String username = "a";
        String password = "aa";
        public String getUsername()
        {
            return username;
        }
        public void setUsername(String username)
        {
            this.username = username;
        }
        public String getPassword()
        {
            return password;
        }
        public void setPassword(String password)
        {
            this.password = password;
        }

        synchronized void printString(String username, String password)
        {
            try
            {
                this.username = username;
                Thread.sleep(100000);
                this.password = password;
            }
            catch(InterruptedException e)
            {

            }
            catch(ThreadDeath e)
            {
                System.out.println(e);
            }
        }
    }

    private static class MyThread extends Thread
    {
        SynchronizedObject obj;

        public MyThread(SynchronizedObject obj)
        {
            super();
            this.obj = obj;
        }

        @Override
        public void run()
        {
            obj.printString("b", "bb");
        }
    }
}

最終輸出:
java.lang.ThreadDeath
b, aa
也就是說加了鎖的printString方法並未執行完成執行緒就被強行終止,導致不可預知的錯誤。

6、不要使用suspend和resume

package com.amuro.studythread.chapter_1_thread;

public class SuspendError
{
    public static void main(String[] args)
    {
        try
        {
            SynchronizedObject obj = new SynchronizedObject();
            Thread t1 = new Thread(new Runnable()
            {

                @Override
                public void run()
                {
                    obj.printString();
                }
            });
            t1.setName("a");
            t1.start();

            Thread t2 = new Thread(new Runnable()
            {

                @Override
                public void run()
                {
                    obj.printString();
                }
            });
            t2.start();

        }
        catch(Exception e)
        {
            e.printStackTrace();
        }


    }

    private static class SynchronizedObject 
    {
        @SuppressWarnings("deprecation")
        synchronized void printString()
        {
            System.out.println(Thread.currentThread().getName() + " : begin");

            if(Thread.currentThread().getName().equals("a"))
            {
                System.out.println(Thread.currentThread().getName() + " : suspend");
                Thread.currentThread().suspend();
            }

            System.out.println(Thread.currentThread().getName() + " : end");
        }
    }
}

最終輸出
a : begin
a : suspend
也就是說如果a執行緒在使用某同步物件為執行完成時就暫停,會導致該物件在其resume之前永遠無法被其他執行緒訪問。

7、yield方法作用是放棄當前CPU使用權,將它讓給其他任務來佔用CPU執行時間。但放棄的時間不確定,可能剛放棄就又拿到了CPU時間片。

8、執行緒優先順序的特性
1)繼承性,A執行緒中啟動B執行緒,A和B具有一樣的優先順序;
2)規則性,CPU會盡量把執行資源讓給優先順序較高的執行緒;
3)隨機性,和2)相關,儘量不代表一定,所以優先順序高的未必會比優先順序低的先執行完

9、守護執行緒

package com.amuro.studythread.chapter_1_thread;

public class Daemon
{
    public static void main(String[] args)
    {
        try
        {
            MyThread mt = new MyThread();
            mt.setDaemon(true);
            mt.start();
            Thread.sleep(5000);
            //當程序中不存在非守護執行緒時,守護執行緒就被自動銷燬

        }
        catch(Exception e)
        {

        }

    }

    private static class MyThread extends Thread
    {
        int i = 0;

        @Override
        public void run()
        {
            while(true)
            {
                try
                {
                    i++;
                    System.out.println("i = " + i);
                    Thread.sleep(1000);
                }
                catch (Exception e) 
                {

                }
            }
        }
    }
}