Javaのプロセスとスレッド
Javaのプロセスは、システムリソースとプログラムコード実行場所のコレクションと見なすことができます。プロセスは、システムによって割り当てられるメモリの最小単位です。スレッド間の通信は困難です。
Javaのスレッドは、プロセスよりも小さな実行単位です。プロセスには1つ以上のスレッドを含めることができます。複数のスレッドがプロセスの独立したJVMメモリユニットを共有します。これには、データ共有や操作の競合などの関連する問題が含まれます。マルチスレッドプログラミングを実行するときは、スレッドの安全性に特別な注意を払う必要があります。
スレッドのライフサイクルは、通常5つの状態、つまり5つのタイプに分けられます。新規(新規)、準備完了(実行可能)、実行中(ブロッキング)、およびデッド(デッド)です。
Javaスレッドクラス
javaのスレッドクラスはjava.lang.Threadです。Threadオブジェクトのインスタンスは、startメソッドを呼び出すことによってスレッドを開始し、スレッドのrunメソッドは、スレッドの開始後に自動的に実行されて関数を実装するビジネスメソッドです。
スレッドには3つのパブリックスレッド()共通コンストラクター、
パブリックスレッド(実行可能なターゲット)、
パブリックスレッド(
実行可能なターゲット、文字列名)、マルチスレッドがあります。アプリケーションでは、複数の順次ストリームが同時に実行されます。(スレッド:順次実行されるコード)
Threadの一般的なメソッドは次のとおりです
。public Thread()新しいスレッドオブジェクト(Threadクラスのコンストラクター)を作成します。デフォルト名はThread-nで、nは0から始まり、
public Thread(Runnable target)を増分する整数です。新しいスレッドを作成します。オブジェクトは、Runnableインターフェイスを実装するクラスのオブジェクトをパラメーターとして受け取ります。デフォルト名はThread-nです。Nは0から始まる整数です
。Public Thread(String name)スレッドオブジェクトを作成し、スレッド名を指定します
public static Thread currentThread( )現在実行中のスレッドオブジェクトを返します
public static void yield()は現在のスレッドオブジェクトを一時停止し、他のスレッドが実行を開始できるようにします(注:yield:yield)
public static void sleep(long millis)は、現在のスレッドを指定されたミリ秒数だけ一時停止します、しかし、このスレッドは獲得したロック
public void start()を失うことなくスレッドを開始します。JVMはこのスレッドのrunメソッドを呼び出します。その結果、2つのスレッドが同時に実行されます。現在のスレッドとrunメソッド
public void run()を実行するスレッドです。スレッドのサブクラスはこのメソッドをオーバーライドする必要があり、コンテンツはスレッドが実行するタスクである必要があります
public final void stop()スレッドを停止し、スレッドによって占有されているオブジェクトロックを解放します
public void interrupt()このスレッドを中断します
public final void join()スレッドAが開始されている場合、joinメソッドを呼び出すと、現在のスレッドを続行する前にスレッドAが終了するまで待機します
public final void join(long millis)スレッドAが以前に開始されている場合、joinメソッドを呼び出すと、指定されたミリ秒数待機するか、スレッドAが終了してから現在のスレッドの実行が続行されます。
スレッドの優先順位を設定し
ます。public final void setPriority(int newPriority)スレッドの優先順位を設定します
public final void setDaemon(Boolean on)現在実行中のスレッドがすべてバックグラウンドスレッドである場合、JVMは実行を停止します。このメソッドは、start()メソッドの前に使用する必要があります(注:デーモン:バックグラウンドプログラム)
public final void checkAccess()は、現在のスレッドがこのメソッドを呼び出すスレッドを変更する権限を持っているかどうかを確認します
public void setName(String name)このスレッドの名前を指定された名前に変更しますパラメータ
public final boolean isAlive()は、スレッドがアクティブであるかどうかをテストし、スレッドが開始されていて停止していない場合はtrueを返します
スレッドを作成するには2つの方法があります。
最初に、ターゲットクラスはThreadクラスを継承し、runメソッドを書き換えて独自のスレッドを作成します。start関数を呼び出して、スレッドコードの実行を開始します。
Threadクラスからサブクラスを派生させ、サブクラスのオブジェクトを作成します。サブクラスはThreadクラスのrunメソッドをオーバーライドし、新しいスレッドで実行する必要があるステートメントセグメントを書き込む必要があります。startメソッドを呼び出すと、新しいスレッドが開始され、runメソッドが自動的に開始されます。コード例は次のとおりです。
public class TestThread {
public static void main(String[] args) {
ThreadOne one = new ThreadOne();
ThreadTwo two = new ThreadTwo();
one.setName("线程一");
two.setName("线程二");
// 设置线程的优先级
two.setPriority(Thread.MIN_PRIORITY);
one.setPriority(Thread.MAX_PRIORITY);
one.start();
two.start();
System.out.println("我是main方法");
}
}
public class ThreadOne extends Thread {
int count = 1;
@Override
public void run() {
while(true){
System.out.println("我是线程:"+this.getName());
if(count ==10){
Thread.yield();
System.out.println("线程暂停");
}
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadTwo extends Thread {
@Override
public void run() {
while(true){
System.out.println("我是线程 "+this.getName());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
次に、Runnableインターフェースを実装するクラスを記述し、ThreadクラスまたはThreadサブクラスのスレッドオブジェクトを初期化するときに、そのクラスのオブジェクトをパラメーターとしてスレッドオブジェクトに渡します。(runメソッドはこのクラスによって提供されます。)Runableインターフェースを使用する利点は、複数のThreadインスタンスがこのインターフェースのrunメソッドを共有できるため、スレッド間の通信がより便利になることです。
public class TestRunnable {
public static void main(String[] args) {
Thread t0 = null;
Thread t2 = null;
MyRannble ran = new MyRannble(t0, t2);
}
public class MyRannble implements java.lang.Runnable {
private Thread th0;
private Thread th2;
int sum = 0;// 存储累加和的结果
int i = 1;// 循环变量
public MyRannble(Thread t0,Thread t2){
if(t0 == null)
th0 = new Thread(this); // th0 与 th2 共享一个实现Runnable接口的实例
if(t2 == null)
th2 = new Thread(this);
th0.setName("线程一");
th2.setName("线程二");
th0.start();// 启动线程t0
try {
th0.join();// join方法将使此线程独占CPU资源,其他线程必需等待此线程执行完毕
} catch (InterruptedException e) {
e.printStackTrace();
}
th2.start();// 启动线程t2
}
@Override
public void run() {
String thName = Thread.currentThread().getName();// 获取当前线程的名字
while(i<=100){
System.out.println("当前线程 "+thName+" 正在计算");
sum+=i++;// 计算累加和
System.out.println("当前的累加和是 "+sum);
if(i==50 && thName.equals("线程一")){
break;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
スレッド間の通信
スレッドの同期を処理する場合、最初に行うことは、キーワードのsynchronizedを使用してデータを変更する方法を変更することです。同期されたキーを使用してメソッドを変更した後、スレッドAがこのメソッドを使用すると、他のスレッドがこのメソッドを使用することになります。スレッドAがこのメソッドの使用を完了するまで待機する必要があります。
同期を使用してスレッドを同期するメカニズムには、同期コードブロック、オブジェクト同期ロック、メソッド同期ロックの3つがあります。
同期コードブロック:同期コードブロックがスレッドオブジェクトによってアクセスされると、他のスレッドはアクセス権を持ちません。現在のスレッドオブジェクトがコードブロックを完全に実行し、同期ロックが解除された場合にのみ、他のスレッドはコードブロックにアクセスできます。
public class SynCode implements Runnable {
@Override
public void run() {
synchronized (this) {
Thread current = Thread.currentThread();// 获取当前线程
for(int i=1;i<=10;i++){
System.out.println("当前执行同步代码块的线程名称是 "+current.getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
オブジェクト同期ロック:
1.共有オブジェクトへのアクセスは条件変数と呼ばれる同期が必要です2.
Java言語では、モニターを介して条件変数を使用してスレッド同期を実現できます
3.モニターは2つのスレッドが条件変数に同時にアクセスできないようにし、ロックのように機能します
4. データでは、スレッド1がメソッドに入る(ロックされる)ときにモニターが取得され、スレッド1のメソッドが実行されるとモニターが解放(ロック解除)され、スレッド2のメソッドが入ることができます。
public class SynObject implements Runnable {
private Dog dog;
public SynObject(){
if(dog == null)
dog = new Dog();
}
@Override
public void run() {
synchronized(dog){
Thread current = Thread.currentThread();
for(int i=1;i<=10;i++){
System.out.println("线程 "+current.getName()+" 在修改dog的名字");
dog.setName("卡尔"+i);
System.out.println(dog.getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
メソッド同期ロック:
synchrinizedによって識別されるメソッドは、相互に排他的なメソッドです。常に、1つのスレッドのみがメソッド(メソッド同期ロック)を実行できることを示します。
public class SynMethod implements Runnable {
private double money = 1000000;
@Override
public void run() {
doMoney();
}
/**
* 同步方法
*/
private synchronized void doMoney(){
Thread t = Thread.currentThread();
for(int i=1;i<=10;i++){
if(t.getName().equals("会计")){
money+=i*10;
System.out.println(t.getName()+"正在整理账户");
}
if(t.getName().equals("出纳")){
money-=i*5;
System.out.println(t.getName()+"正在支取钱");
}
System.out.println("当前账号金额是 "+money);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}