ホームページ  >  記事  >  Java  >  プロセスとスレッドとは何ですか?

プロセスとスレッドとは何ですか?

零下一度
零下一度オリジナル
2017-06-25 10:18:251858ブラウズ

1 概要

1. プロセスとは何ですか?

プロセスは比較的独立した実行単位です。

2. スレッドとは何ですか?

プロセスの一部、つまりプロセス内の実際のタスク実行者は、プロセスにアタッチする必要があります。スレッドのプロセスへの依存は主に次の点に反映されます。

  • スレッドはプロセスなしでは開始できず、プロセスが開始されるという前提で開始する必要があります。

  • スレッドはプロセスからデータを取得する必要がある場合があります。

3. スレッドとプロセスの違いは何ですか?

スレッドとプロセスは 2 つの相対的な概念であり、オブジェクトは、それが属する上位実行者の観点からはプロセスと呼ばれます。

4. マルチスレッドの設計目的、用途、意義

CUP は一度に 1 つのスレッドしか実行できません。マルチスレッドの本質は、複数のタスクを高速に交互に実行することです。複数のスレッド間でデータ交換がない場合、

を独立して実行することはできません。マルチスレッドを使用しても、合計の実行時間を短縮することはできません。

マルチスレッド設計の主な目的は、実行速度を上げることではなく、各スレッドを比較的均等に実行して、特定のスレッドが CPU タイム スライスを長時間保持せず、

他のスレッドが長時間占有しないようにすることです。長い間待っています。 CPUのタイムスライスが複数のスレッドを素早く切り替えるため、人間の感覚では感知できる範囲を超え、複数のタスクが実行されているように感じられます。

たとえば、複数の人が同じ Web サイトにアクセスする場合、マルチスレッドが使用されておらず、同時に Web サイトにアクセスできるのは 1 人だけである場合、他のほとんどの人は 5 分かかります。 5 分間待つ必要があります。ユーザー エクスペリエンスは非常に悪いです。これはマルチスレッドを使用し、1 人のユーザーが入力した後、CPU が他のユーザーに切り替わり、他のユーザーが次々に入力できるようになりますが、合計の実行時間は短縮されません。

5. CPU スケジューリング モード

タイムシェアリング スケジューリング モード: システムは CPU タイム スライスを各スレッドに均等に割り当てます。

  • プリエンプティブ スケジューリング モード: 各スレッドは CPU タイム スライスをめぐって競合し、CPU タイム スライスはスレッド間で不均等に分散されます。

  • 2 番目のスレッドの作成

1. Java SE API では、スレッドを作成する 2 つの方法が提供されます:

Runnable インターフェースを実装し、実装クラスのオブジェクトをパラメータとして Thread コンストラクターに渡します。真ん中。

  • Thread クラスを直接継承します。

  • 2. どのメソッドを使用する場合でも、実行する必要があるタスクは run メソッドに配置する必要があります。

3. 2 つの作成方法の違い:

⑴Java は単一継承を使用します。つまり、クラスは 1 つの親クラスのみを継承でき、クラスは複数のインターフェイスを実装し、Thread を継承することでスレッドを作成できます。これにより、

このクラスは唯一の継承の機会を失います。

⑵リソース共有を実現するにはさまざまな方法があります

  • まず第一に、リソース共有は Thread を継承してスレッドを作成することによっても実現できることを明確にする必要がありますが、new キーワードによって作成された複数のスレッドは異なります オブジェクト、および共有リソースは、通常はコンストラクター インジェクションを通じて外部からのみ取得できます。

  • Runnable インターフェースを実装してスレッドを作成すると、同じ実装クラスのオブジェクトを使用して複数のスレッドを作成し、リソースの共有を実現でき、共有リソースはスレッド内から取得されます。

4. Runnable インターフェイスを実装してスレッドを作成すると、唯一の継承の機会が保持されるだけでなく、リソース共有操作が比較的簡単になるため、この方法は通常、スレッドの作成に使用されます。

5. Threadを継承してリソース共有を実現する:

共有リソースの外部クラスを提供する

package com.test.thread.extendsThread;public class MyClass {public int count;

}
Thread thread subclass

package com.test.thread.extendsThread;public class MyThread extends Thread {private MyClass obj;public MyThread() {super();
    }public MyThread(MyClass obj) {super();this.obj = obj;
    }

    @Overridepublic void run() {
        System.out.println("obj=" + obj);while (true) {synchronized (obj) {if (obj.count > 0) {try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "----当前数量=" + obj.count--);
                } elsereturn;
            }
        }

    }

}
テストクラス

りー

 

三 线程生命周期

1.什么是线程的生命周期?

由不同阶段构成的线程从出生到死亡的整个过程,叫做线程的生命周期。

2.线程生命周期的意义

了解线程的生命周期能够更好地掌握线程的运行情况,比如线程的就绪状态,意味着不是调用start方法之后,线程立即执行。

3.生命周期的几个阶段:

  • 出生状态:线程创建完成,尚未开启前的状态。

  • 就绪状态:调用start方法开启线程,线程尚未运行的状态。

  • 运行状态:线程获取CPU时间片执行时的状态。

  • 休眠状态:线程调用sleep方法后进入指定时长的休眠状态,时间结束进入就绪状态。

  • 等待状态:监听对象在线程内部调用wait方法后,线程失去对象锁,进入等待状态。

  • 阻塞状态:线程发出输入或者输出请求后进入阻塞状态。

  • 死亡状态:run方法执行完毕,线程死亡。

四 线程的加入

一个线程A在另一个线程B内部调用join方法,B线程中止,A线程开始执行,A线程执行完毕,B线程才开始执行。

五 线程优先级

线程优先级设定了线程获取CPU时间片的概率,仅仅是一种概率,不能保证优先级高的线程一定优先获得CPU时间片。

线程优先级分为10个等级,从1-10,数值越大,优先级越高,通过setProprity(int)方法设置。

六 线程礼让

Thread.yield,线程礼让只是通知当前线程可以将资源礼让给其他线程,并不能保证当前线程一定让出资源。

七 同步机制

1.什么是线程同步机制?

使得同一资源同一时刻只能有一个线程访问的安全机制,即一个线程访问完毕,其他线程才能访问。

2.同步机制的目的

由于目标资源同一时刻只有一个线程访问,解决了线程安全问题。

3.什么是线程安全问题?

⑴线程安全问题产生条件

  • 多线程并发访问。

  • 存在可修改的共享数据。

⑵第一个线程获取了共享数据,操作结束前,第二个线程修改了该数据,导致第一个线程运算时采用的不是获取时的数据。

4.同步机制解决线程安全问题的原理

synchronized(共享对象){ 修改共享数据的代码 }

上述操作给修改共享数据的代码加了一把对象锁。任何一个对象只有一把对象锁,线程只有获得了对象锁才能访问加锁的资源。一个线程获取了对象锁,执行加锁的代码,执行完毕,归还对象锁,其他线程开始争夺对象锁,访问资源。

5.类锁

synchronized关键字加到静态方法上时,形成类锁,执行该方法上必须获取类锁。

类锁与对象锁是两种不同的锁,允许一个线程持有类锁,另一个线程持有对象锁。

6.synchronized关键字

synchronized关键字加在成员方法,该方法成为同步成员方法,由于一个对象只有一把对象锁,一个线程访问了一个同步成员方法,其他线程不能访问其他同步成员方法。

同步方法不可以被继承,同步方法在子类中失去同步机制。

7.判断条件的设置

在同步机制中,如果同步代码的执行需要满足一定条件,那么将判断条件放在锁内,保证当前获取了锁的线程在执行同步代码时满足执行条件。如果放在锁外,有可能出现当前线程获取了锁以后不满足执行条件的情况。

不存在线程安全问题的做法:

public void run() {
        System.out.println("obj=" + obj);while (true) {synchronized (obj) {if (obj.count > 0) {try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "----当前数量=" + obj.count--);
                } elsereturn;
            }
        }

    }

while文にobj.count>0という判定条件を置いた場合、スレッドがwhile文に入ったときにカウントが1になって条件を満たして入ってオブジェクトロックの獲得を待つということが起こる可能性があります。現在オブジェクトロックを保持しているスレッドが実行を完了するとカウントが0になり、待機中のスレッドがオブジェクトロックを取得します。 count=0の場合、同期ブロックが実行され、判定条件は無効になります。

8 デッドロック

1. デッドロックとは何ですか?

スレッド A は複数のロックを必要とします。スレッド B は A に不足しているロックを保持し、A が保持しているロックを欠如しています。スレッドはすべてのロックを取得する前に保持しているロックを解放しないため、

これによりスレッド A が存在します。スレッド B との膠着状態が発生し、プロセス全体が停止します。

2. デッドロックを回避するにはどうすればよいですか?

同期メカニズム内のロックの数を減らし、同じロックが複数の場所に表示されるのを避けるようにしてください。

9つのデーモンスレッド

1. ユーザースレッド?

一般に、作成されるスレッドはユーザー スレッドです。つまり、スレッドはデーモン スレッドとして明示的に設定されておらず、デーモン スレッド内で作成されません。

2. メインスレッドはユーザースレッドに属します。

3. デーモンスレッドとは何ですか?

バックグラウンドで実行され、ユーザーのスレッドにサービスを提供するスレッド。

4. デーモンスレッドの作成

ユーザースレッドは setDaemon(true) メソッドを呼び出すか、デーモンスレッド内にスレッドを作成します。

5. デーモン スレッドの役割

デーモン スレッドは、ガベージ コレクターなどのサービスをユーザー スレッドに提供するために使用されます。

6. この時点でデーモンスレッドが実行を完了したかどうかに関係なく、すべてのユーザースレッドが実行を完了すると、JVM は終了します。

7. デーモン スレッドはバックグラウンドで実行され、すべてのユーザー スレッドが終了すると自動的に終了します。

10 wait メソッドと sleep メソッドの比較

1. 存在スコープ

  • wait メソッドはオブジェクトレベルです。つまり、Java のすべてのオブジェクトがこのメソッドを持ちます (toString と同様)。

  • sleep メソッドは Thread とそのサブクラスにのみ存在します。

2. 関数

  • sleep は、現在のスレッドをスリープさせ、CPU タイムスライスを解放しますが、保持されているロックは解放しません。

  • waitはスレッド間通信に使用され、オブジェクトはそのオブジェクトをロックとして使用するすべてのスレッドを管理します。同期コード内のロック オブジェクトによって呼び出されると、現在のスレッドが

    によって保持されているオブジェクト ロックを解放します。

3. 使用方法

  • sleepメソッドは静的メソッドであり、Thread.sleepを通じて直接呼び出されます。

  • は同期コードで使用され、ロック オブジェクトによって呼び出されます。

4. 関連メソッド

  • obj.notify(): オブジェクト リスナーのスレッドをランダムに起動し、オブジェクト ロックと CPU タイム スライスが取得されると、スレッドは準備完了状態になります。 、待機している場所から開始されます。その後、実行します。

    は、実行メソッドや同期コードを再入力しません。

  • obj.notifyAll(): オブジェクトリスナー上で待機しているすべてのスレッドを起動し、すべてを準備完了状態にします。

十一 ThreadLocal

1.线程局部变量,为每一个线程提供一个变量的副本,使得各个线程相对独立地操作变量,避免线程安全问题。

2.首先必须明确一点,ThreadLocal.get()获取的变量副本必须手动传入:

ThreadLocal.set(Object obj)

初次获取时,判断线程局部变量中是否保存有变量副本,如果没有则手动传入,在该线程中下次获取的就是初次传入的对象。

3.ThreadLocal的目的是保证在一个线程内部,一次创建,多次获取。

4.基本原理:
      将初次传入的变量与线程绑定,线程不变,变量不变。

十二 GroboUtils多线程测试

   1.JUnit测试不支持多线程,GroboUtils提供了对多线程测试的支持,使用时需要导入架包。

    2.几个比较重要的类:

  • TestRunnable:实现了Runnable接口,run方法中运行的是runTest方法,runTest方法是一个抽象方法。

  • MultiThreadedTestRunner:负责管理并开启多个线程。

    3.测试步骤

⑴继承TestRunnable,实现其中的抽象方法runTest,将需要运行的代码放入该方法中。通常为子类定义一个有参构造方法,方法形参为需要测试的线程,在runTest方法中调用测试线程的run方法,从而将将需要执行的代码注入runTest方法中。

⑵创建测试线程数组,将需要测试的TestRunnable实现类传入其中:

TestRunnable[] tr=new TestRunnable[len];

⑶根据测试线程数组创建线程管理与运行对象并开启多线程:

MultiThreadedTestRunner mttr=new MultiThreadedTestRunner(tr);
mttr.runTestRunnables();

以上がプロセスとスレッドとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。