はじめに高度なマルチスレッドのJava ---

人々は離れて取ることができないことをこの世界に三つのことがあります。まず、第二は、夢の中で隠されている、食品の胃に食べ、三冊は、脳に読み込まれ

マルチスレッドのクイックスタート

1、スレッドとプロセスとの間の差

  • システム上で実行されている各プログラムは、プロセスです。各プロセスは、1つ以上のスレッドが含まれています。スレッドは、命令のセット、または独立してプログラムで実行可能なプログラムの特別なセクションの集合です。だから、基本的には単一のプログラムで複数のタスクを実行する責任がある軽量プロセススレッド、。オペレーティングシステムによるスケジューリングと、複数のスレッドを実行するための通常責任を負います。

  • プログラムの速度を実行している、に対処するために、バックグラウンドタスクにプログラムで長い時間を占めることができるスレッドを使用すると、ユーザーの入力を待っているように、いくつかのタスクの実現に加速する可能性がある、ファイルは読み取りと書き込み、およびネットワークデータを送受信し、スレッドがより有用です。この場合、あなたは、このようなメモリの使用量としてなど、いくつかの貴重なリソースを解放することができます。

  • オペレーティングシステムがそれらを切り替える必要があるため、多数のスレッドが、パフォーマンスに影響を与えることができれば、より多くのスレッドがより多くのメモリ空間を必要とする、スレッドのサスペンションは、プログラムの実行への影響を考慮する必要があります。典型的には、モデル・データ・ブロックは、複数のスレッド間で共有され、スレッドは、デッドロック状況を回避する必要があります。

  • 要約:プロセスは、すべてのスレッドの組であり、各スレッドは、実行プロセスのパスです。

2.なぜマルチスレッドを使うのか?

  • (1)は、複数のスレッドを使用することができるプログラムの応答時間を短縮しますあなたはシングルスレッドまたは閉塞を待たなければならない場合、プログラムは、マウス、キーボードなどの操作に応答しない原因となり、複数のスレッドを使用すると、この問題は、強化された対話型プログラムを解決することができます。

  • (2)プロセス、スレッドと比べて作成およびスイッチングオーバーヘッド小さいメモリ空間スレッドがようにコード・セグメントは、データセグメントを共有しているため、。

  • (3)、マルチコアCPU、マルチコアコンピュータ自体は、単一のスレッド場合、あなたはしない再利用のコンピューティングリソースすることができ、マルチスレッド実行する能力を有する資源の巨大な浪費をもたらします。

  • (4)、マルチスレッドができ、プログラムの構造を簡素化、維持するためにプログラムを容易に、非常に複雑なプロセスは、実行の複数のスレッドに分割することができます。

3、マルチスレッドアプリケーションのシナリオ?

  • メインは、効率を向上させるマルチスレッドプログラムを具現化します。
  • 例:サンダーマルチスレッドダウンロード、データベース接続プーリング、バッチようにテキストメッセージを送信して。

図4に示すように、マルチスレッドの方法は作成します

まず、Threadクラスの継承は、runメソッドをオーバーライドします

class CreateThread extends Thread {
    // run方法中编写 多线程需要执行的代码
    publicvoid run() {
        for (inti = 0; i< 10; i++) {
            System.out.println("i:" + i);
        }
    }
}
publicclass ThreadDemo {

    publicstaticvoid main(String[] args) {
        System.out.println("-----多线程创建开始-----");
        // 1.创建一个线程
        CreateThread createThread = new CreateThread();
        // 2.开始执行线程 注意 开启线程不是调用run方法,而是start方法
        System.out.println("-----多线程创建启动-----");
        createThread.start();
        System.out.println("-----多线程创建结束-----");
    }

}

  • startメソッドが呼び出された後、コードは上から下に実行されなかったが、新しい行政府があります

  • 注意:ペイントデモは、異なる実行パスをマルチスレッド。

第二に、、Runnableインタフェースを達成するために、runメソッドをオーバーライドします

class CreateRunnable implements Runnable {

    @Override
    publicvoid run() {
        for (inti = 0; i< 10; i++) {
            System.out.println("i:" + i);
        }
    }

}
publicclass ThreadDemo2 {
    publicstaticvoid main(String[] args) {
        System.out.println("-----多线程创建开始-----");
        // 1.创建一个线程
        CreateRunnable createThread = new CreateRunnable();
        // 2.开始执行线程 注意 开启线程不是调用run方法,而是start方法
        System.out.println("-----多线程创建启动-----");
        Thread thread = new Thread(createThread);
        thread.start();
        System.out.println("-----多线程创建结束-----");
    }
}

第三に、匿名内部クラスの方法の使用

 System.out.println("-----多线程创建开始-----");
         Thread thread = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i< 10; i++) {
                    System.out.println("i:" + i);
                }
            }
        });
         thread.start();
         System.out.println("-----多线程创建结束-----");

5、継承Threadクラスや優れた実装、Runnableインタフェースを使用していますか?

  • それは良い理由の継承を続けることができるインターフェイスを実装を実現するために、Runnableインタフェースを実装して、クラスは継承できません。

6は、開始スレッド開始方法はまだ実行メソッドを使用して呼ばれているのですか?

  • オープンスレッドではなく、実行方法に注意を呼び出すの実行スレッドを開始しますが、startメソッドは、runメソッドは、インスタンスの知識を呼び出して呼び出します。

7、およびスレッドを取得するオブジェクトの名前

共通テーマAPIメソッド
開始() スレッドを開始
currentThread() 現在のスレッドオブジェクトを取得します。
getId() この番号は0から始まり、現在のスレッドのIDスレッド番号を取得します。
getName() 現在のスレッドの名前を取得します。
スリープ(ロングミル) 眠れる森のスレッド
やめる() スレッドを停止し、
一般的なスレッドのコンストラクタ
糸() 新しいThreadオブジェクトを割り当て
スレッド(文字列名) その名の通り指定された名前を持つ新しいThreadオブジェクトを割り当てます。
スレッド(Runable R) 新しいThreadオブジェクトを割り当て
スレッド(Runable R、文字列名) 新しいThreadオブジェクトを割り当て

8、デーモンスレッド

  • Javaは、2件のスレッドがあり、一方が他方のスレッドの守護者である、ユーザスレッドです。
  • ユーザスレッドは、メインスレッドがユーザスレッドを停止することはありません、停止するように作成したユーザー定義のスレッドを参照します
  • プロセスが存在するか、メインスレッドを停止しないデーモンスレッドは、スレッド・デーモンが停止されます。
  • デーモンスレッドを設定するためには、setdaemon(true)メソッドを使用します
public class DaemonThread {

    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(100);
                    } catch (Exception e) {
                        // TODO: handle exception
                    }
                    System.out.println("我是子线程...");
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {

            }
            System.out.println("我是主线程");
        }
        System.out.println("主线程执行完毕!");
    }

}

図9に示すように、マルチスレッド動作状態

  •  作成からスレッド、常に次の5つのいずれかの状態で最後に実行します。新しい状態レディ状態実行状態状態を遮断し、死の状態

新しいステータス

  • 当用new操作符创建一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码

就绪状态

  • 一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。
  • 处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由Java运行时系统的线程调度程序(thread scheduler)来调度的。

运行状态

  • 当线程获得CPU时间后,它才进入运行状态,真正开始执行run()方法.
    阻塞状态线程运行过程中,可能由于各种原因进入阻塞状态:

      1>线程通过调用sleep方法进入睡眠状态;
      2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;

       3>线程试图得到一个锁,而该锁正被其他线程持有;
       4>线程在等待某个触发条件;

死亡状态

  • 有两个原因会导致线程死亡:
     - - 1) run方法正常退出而自然死亡,
     - - 2) 一个未捕获的异常终止了run方法而使线程猝死。
    -  为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.

join()方法作用

  • 当在主线程当中执行到t1.join()方法时,就认为主线程应该把执行权让给t1

创建一个线程,子线程执行完毕后,主线程才能执行。

Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        Thread.sleep(10);
                    } catch (Exception e) {

                    }
                    System.out.println(Thread.currentThread().getName() + "i:" + i);
                }
            }
        });
        t1.start();
        // 当在主线程当中执行到t1.join()方法时,就认为主线程应该把执行权让给t1
        t1.join();
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(10);
            } catch (Exception e) {

            }
            System.out.println("main" + "i:" + i);
        }
        
  • 优先级
  • 现代操作系统基本采用时分的形式调度运行的线程,线程分配得到的时间片的多少决定了线程使用处理器资源的多少,也对应了线程优先级这个概念。在JAVA线程中,通过一个int priority来控制优先级,范围为1-10,其中10最高,默认值为5。下面是源码(基于1.8)中关于priority的一些量和方法。
class PrioritytThread implements Runnable {

    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().toString() + "---i:" + i);
        }
    }
}
public class ThreadDemo4 {

    public static void main(String[] args) {
        PrioritytThread prioritytThread = new PrioritytThread();
        Thread t1 = new Thread(prioritytThread);
        Thread t2 = new Thread(prioritytThread);
        t1.start();
        // 注意设置了优先级, 不代表每次都一定会被执行。 只是CPU调度会有限分配
        t1.setPriority(10);
        t2.start();
        
    }

}

Yield方法

Thread.yield()方法的作用:暂停当前正在执行的线程,并执行其他线程。(可能没有效果)
yield()让当前正在运行的线程回到可运行状态,以允许具有相同优先级的其他线程获得运行的机会。因此,使用yield()的目的是让具有相同优先级的线程之间能够适当的轮换执行。但是,实际中无法保证yield()达到让步的目的,因为,让步的线程可能被线程调度程序再次选中。
结论:大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。

总结

  • 1.进程与线程的区别?
    • 答:进程是所有线程的集合,每一个线程是进程中的一条执行路径,线程只是一条执行路径。
  • 2.为什么要用多线程?
    • 答:提高程序效率
  • 3.多线程创建方式?
      • 答:继承Thread或Runnable 接口。
  • 4.是继承Thread类好还是实现Runnable接口好?
    • 答:Runnable接口好,因为实现了接口还可以继续继承。继承Thread类不能再继承。
  • 5.你在哪里用到了多线程?
    • 答:主要能体现到多线程提高程序效率。
    • 举例:分批发送短信、迅雷多线程下载等。

总结不易,给个关注吧 https://github.com/yunlongn

おすすめ

転載: www.cnblogs.com/rolandlee/p/10967171.html