ホームページ > 类库下载 > java类库 > Java マルチスレッドの基本的な使用法

Java マルチスレッドの基本的な使用法

高洛峰
リリース: 2016-11-14 09:32:47
オリジナル
1843 人が閲覧しました

1. 概念

1. プロセス

1.1 プロセス: 各プロセスの実行には、実行パス、または制御単位があります。

1.2 スレッド: プロセス内の独立した制御単位であり、プロセス内に少なくとも 1 つのスレッドが存在します。

1.3 Java VM の例:

Java VM が起動すると、Java プログラムの実行を担当するプロセス java.exe が存在し、このスレッドによって実行されるコードが存在します。 main メソッド内でこのスレッドをメインスレッドと呼びます。拡張: 実際、JVM は複数のスレッドとガベージ コレクション メカニズムを担当するスレッドを起動します。 2. マルチスレッドの重要性: 実行効率の向上。 1. マルチスレッドの作成 1つ目はThreadクラスを継承する方法です

1.1 Threadクラスを継承するクラスを定義し、Threadクラスのrunメソッドをオーバーライドしてカスタマイズしたコードをrunメソッドに格納してスレッドを実行させます。

1.2 スレッドの start メソッドを呼び出す このメソッドには、スレッドの開始と run メソッドの呼び出しの 2 つの機能があります。

1.3 複数のスレッドで実行する場合、複数のスレッドが CPU の実行権限を取得するため、実行結果は毎回異なります。そして、CPU が実行するプログラムは 1 つだけです。 (マルチコアを除く)、CPU は急速に切り替わり、同時に実行されているように見える効果を実現します。 CPU の実行能力を争うマルチスレッドの実行動作を視覚化できます。これはマルチスレッドのランダム性の特徴です。どれくらいの時間がかかるかについては、CPU が最終決定権を持っています。

public class Demo extends Thread{ 
    public void run(){ 
        for (int x = 0; x < 60; x++) { 
            System.out.println(this.getName()+"demo run---"+x); 
        } 
    } 
     
    public static void main(String[] args) { 
        Demo d=new Demo();//创建一个线程 
        d.start();//开启线程,并执行该线程的run方法 
        d.run(); //仅仅是对象调用方法,而线程创建了但并没有运行 
        for (int x = 0; x < 60; x++) { 
            System.out.println("Hello World---"+x); 
        } 
    } 
 
}
ログイン後にコピー

2 マルチスレッドを作成する 2 番目の方法の手順:

2.1 Runnable インターフェイスを実装するクラスを定義する

2.2 Runnable インターフェイスの run メソッドをオーバーライドする: スレッドによって実行されるコードを run に格納するメソッド

2.3. 渡す Thread クラスはスレッド オブジェクトを作成します

2.4. Runnable インターフェイスのサブクラス オブジェクトを実パラメータとして Thread クラスのコンストラクターに渡します

なぜ Runnable インターフェイスのサブクラス オブジェクトを渡す必要があるのですかThread のコンストラクター: カスタム run メソッドのため、これが属するオブジェクトは Runnable インターフェイスのサブクラス オブジェクトであるため、スレッドが指定されたオブジェクトの run メソッドを実行するには、実行先のオブジェクトを明確にする必要があります。メソッドが属します

2.5. Thread クラスの start メソッドを呼び出してスレッドを開始し、Runnable インターフェイスのサブクラスメソッド

を呼び出します。実装は、単一の制限を回避します。スレッドを定義するときに実装を使用することをお勧めします

3.2. Thread クラスを継承する: スレッドのコードはサブクラスの run メソッドに格納されます

3. Runnable を実装する: スレッドのコードはサブクラスの run メソッドに格納されます。インターフェース

4. マルチスレッド - run と start の特徴

4.1 run メソッドを上書きする理由:

Thread クラスはスレッドを記述するために、スレッドによって実行されるコードを格納する関数を定義します。 . storage 関数は run メソッドです。つまり、Thread クラスの run メソッドは、スレッドによって実行されるコードを保存するために使用されます

5. thread-run---sleep を作成します。 ()/wait()--freeze---notify()---wake up

Create thread-run---stop()-die

create Thread-run---CPU 実行権を取得しませんでした--一時的に凍結されています

6. スレッドオブジェクトとその名前を取得します

6.1. スレッドには独自のデフォルト名があり、番号は0から始まります

6.2.static Thread currentThread() :現在のスレッドオブジェクトを取得します

6.3 .getName(): スレッド名を取得します

6.4. スレッド名を設定します: setName() またはコンストラクターを使用します

3. マルチスレッドのセキュリティの問題

1.データを共有するために複数のステートメントが同じスレッド上で動作している場合、1 つのスレッドが複数のステートメントの一部のみを実行し、実行が完了する前に別のスレッドが実行に参加するため、共有データ エラーが発生します

解決策: 1.2 の場合。 1.3. Java は、コード ブロックを同期するという専門的なソリューションを提供します。 :

Synchronized (オブジェクト) {同期する必要があるコード}。 オブジェクトはロックのようなもので、ロックを保持していないスレッドは、CPU を取得しても同期して実行できます。 CPU 実行権。ロックが取得されていないためです

2. 同期の前提条件: 2 つ以上のスレッドが必要です

2.2. 利点は、次のとおりです。マルチスレッドのセキュリティ問題は解決されています

2.4. 欠点は、複数のスレッドがロックを決定する必要があり、より多くのリソースを消費することです

同期関数を定義し、メソッド内で synchronized を使用して変更します

/* 
 * 需求:简易买票程序,多个窗口同时卖票 
 */ 
public class Ticket implements Runnable { 
    private static int tick = 100; 
    Object obj = new Object(); 
    boolean flag=true; 
 
    public void run() { 
        if(flag){ 
            while (true) { 
                synchronized (Ticket.class) { 
                    if (tick > 0) { 
                        System.out.println(Thread.currentThread().getName() 
                                + "code:" + tick--); 
                    } 
                } 
            } 
        }else{ 
            while(true){ 
                show(); 
            } 
        } 
         
    } 
 
    public static synchronized void show() { 
        if (tick > 0) { 
            System.out.println(Thread.currentThread().getName() + "show:" 
                    + tick--); 
        } 
    } 
 
} 
 
class ThisLockDemo { 
    public static void main(String[] args) { 
        Ticket t = new Ticket(); 
 
        Thread t1 = new Thread(t); 
        try { 
            Thread.sleep(10); 
        } catch (Exception e) { 
            // TODO: handle exception 
        } 
        t.flag=false; 
        Thread t2 = new Thread(t); 
        //Thread t3 = new Thread(t); 
        //Thread t4 = new Thread(t); 
 
        t1.start(); 
        t2.start(); 
        //t3.start(); 
        //t4.start(); 
    } 
}
ログイン後にコピー

6. 同期ロック

6.1 関数はオブジェクトによって呼び出される必要があり、その場合、関数はそれが属するオブジェクトへの参照を持ちます。したがって、同期関数によって使用されるロックは this

6.2 です。静的関数のロックはクラスオブジェクトです

静的にメモリに入るとき、このクラスのオブジェクトはありませんが、このクラスに対応するバイトコードファイルオブジェクト、クラス名.classが存在する必要があります。オブジェクトの型はクラス

6.3. 静的同期メソッド、使用されるロックはメソッドが配置されているクラスのバイトコードファイルです。クラス名.class

public class Test extends Thread{ 
     
    Test(String name){ 
        super(name); 
    } 
     
    public void run(){ 
        for (int x = 0; x < 60; x++) { 
            System.out.println((Thread.currentThread()==this)+"..."+this.getName()+" run..."+x); 
        } 
    } 
} 
 
class ThreadTest{ 
    public static void main(String[] args) { 
        Test t1=new Test("one---"); 
        Test t2=new Test("two+++"); 
        t1.start(); 
        t2.start(); 
        t1.run(); 
        t2.run(); 
        for (int x = 0; x < 60; x++) { 
            System.out.println("main----"+x); 
        } 
    } 
}
ログイン後にコピー

7. マルチスレッド、シングルトンモード遅延スタイル

懒汉式与饿汉式的区别:懒汉式能延迟实例的加载,如果多线程访问时,懒汉式会出现安全问题,可以使用同步来解决,用同步函数和同步代码都可以,但是比较低效,用双重判断的形式能解决低效的问题,加同步的时候使用的锁是该类锁属的字节码文件对象

/* 
 * 单例模式 
 */ 
//饿汉式 
public class Single { 
    private static final Single s=new Single(); 
    private Single(){} 
    public static Single getInstance(){ 
        return s; 
    } 
 
} 
 
//懒汉式 
class Single2{ 
    private static Single2 s2=null; 
    private Single2(){} 
    public static Single2 getInstance(){ 
        if(s2==null){ 
            synchronized(Single2.class){ 
                if(s2==null){ 
                    s2=new Single2();     
                } 
            } 
        } 
        return s2; 
    } 
} 
 
class SingleDemo{ 
    public static void main(String[] args) { 
        System.out.println("Hello World"); 
    } 
}
ログイン後にコピー

8.多线程-死锁

同步中嵌套同步会出现死锁

/* 
 * 需求:简易买票程序,多个窗口同时卖票 
 */ 
public class DeadTest implements Runnable { 
    private boolean flag; 
 
    DeadTest(boolean flag) { 
        this.flag = flag; 
    } 
 
    public void run() { 
        if (flag) { 
            synchronized(MyLock.locka){ 
                System.out.println("if locka"); 
                synchronized(MyLock.lockb){ 
                    System.out.println("if lockb"); 
                } 
            } 
        } else { 
            synchronized(MyLock.lockb){ 
                System.out.println("else lockb"); 
                synchronized(MyLock.locka){ 
                    System.out.println("else locka"); 
                } 
            } 
        } 
    } 
} 
 
class MyLock{ 
    static Object locka=new Object(); 
    static Object lockb=new Object(); 
} 
 
class DeadLockDemo { 
    public static void main(String[] args) { 
        Thread t1 = new Thread(new DeadTest(true)); 
        Thread t2 = new Thread(new DeadTest(false)); 
 
        t1.start(); 
        t2.start(); 
    } 
}
ログイン後にコピー


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート