プロセスとスレッドの関係
プロセスはすべてのスレッドのコレクションであり、各スレッドはプロセスの実行パスです。
プロセスとは何ですか、スレッドとは何ですか
プロセス、システム上で実行されているすべてのプログラムはプロセスです。
スレッドスレッドは、一連の命令またはプログラムの特別なセクションです。プログラム内で個別に実行できます。各プロセスには、1つ以上のスレッドが含まれます。
マルチスレッドの利点(同期および非同期の概念に類似)
☞タスク実行の効率を向上させる
☞スレッド(タスク)は相互に影響を与えません。一方のスレッドがハングした場合、もう一方は通常どおり実行されます
Javaでスレッドを作成する3つの方法
1.Threadクラスを継承します
☞継承されたクラスInheritThreadを作成し、run()メソッドをオーバーライドします
public class InheritThread extends Thread {
@Override
public void run() {
System.out.println("run()方法被执行...");
}
}
☞メインスレッドクラスThreadDemoを作成し、main()メソッドで継承されたクラスを呼び出します
public class ThreadDemo {
public static void main(String[] args) {
System.out.println("创建新线程...");
InheritThread inheritThread = new InheritThread();
inheritThread.start(); //启动一个线程是调用start()方法,而不是直接调用run()方法
System.out.println("新线程已启动...");
System.out.println("main()方法启动...");
}
}
結果:
ps:run()メソッドを直接呼び出して実行することは、新しいスレッドを再起動する代わりにメインスレッドで実行することと同じです。マルチスレッドの実行シーケンスはクロス実行ですが、上記の結果ではクロス実行の効果を確認できませんが、スレッドが実行回数が十分に多い場合(ループなど)、クロス実行の効果を反映させることができます。
2. Runnableインターフェイスを実装します(推奨)
Runnableインターフェイスを実装する実装クラスImplementRunnableを作成します
public class ImplementRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++){
System.out.println("run()==>"+i);
}
}
}
メインスレッド
ImplementRunnable implementRunnable = new ImplementRunnable();
System.out.println("创建新线程...");
Thread thread = new Thread(implementRunnable); //传入对象,无法直接调用start()方法
thread.start();
System.out.println("新线程已启动...");
System.out.println("main()方法启动...");
for (int i = 0; i < 100; i++){
System.out.println("main()==>"+i);
}
ps:スレッドの継承は、インターフェイスRunnableの実装と同じ機能を持ちますが、インターフェイスは複数で実装でき、継承は継承することしかできないため、インターフェイスの実装方法を使用することをお勧めします。
3.匿名の内部クラスを使用する
他のクラスを作成する必要はありません。メインスレッドで匿名の内部クラスを作成するだけです。
System.out.println("创建新线程...");
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("run()==>" + i);
}
}
}).start();
System.out.println("新线程创建成功...");
for (int i = 0; i < 100; i++){
System.out.println("main()==>"+i);
}
一般的に使用される方法
1、sleep()
☞現在のスレッドを実行状態からスリープ状態に変更します。スリープ時間が経過すると、スレッドは実行状態に戻ります(クロス実行の効果は、遅延を使用して明確に確認できます)。
☞ロックを解除できません
@Override
public void run() {
for (int i = 0; i < 10; i++){
try { //在run()方法中不能抛出异常,只能捕获异常
Thread.sleep(1000); //延时1秒
} catch (InterruptedException e) {
}
System.out.println("i="+i);
}
}
2.スレッドの名前を設定します
public class TestThread extends Thread {//只有使用继承的方式才能使用getId()方法和getName()方法
@Override
public void run() {
for (int i = 0; i < 10; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("线程ID:"+getId()+" 线程名称:"+getName()+" ==>>i="+i);
}
}
}
public static void main(String[] args) {
TestThread thread = new TestThread();
thread.setName("线程1");
thread.start();
TestThread thread2 = new TestThread();
thread2.setName("线程2");
thread2.start();
}
インターフェイスを実装する方法を使用する
public class TestThread2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
Thread thread = Thread.currentThread(); //获取当前线程,才能调用具体的设置方法
System.out.println("线程ID:"+thread.getId()+" 线程名称:"+thread.getName()+" ==>>i="+i);
}
}
}
TestThread2 testThread2 = new TestThread2();
Thread thread = new Thread(testThread2);
thread.start();
上記と同じ効果
3. join()メソッドの使用
☞優先度を上げ、スレッドが実行されるまで待ってから他のスレッドを実行します
public static void main(String[] args) {
Thread threadJoin = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 60; i++) {
System.out.println("子线程i: " + i);
}
}
});
threadJoin.start();
try {
threadJoin.join(); //提高子线程的优先级
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 30; i++) {
System.out.println("主线程: "+i);
}
System.out.println("主线程执行完毕...");
}
☞効果
マルチスレッド実行状態(5種類)
新しい状態==》準備完了状態==》実行状態==》休止状態==》死の状態
新しい状態:作成されましたが、start()メソッドを呼び出さなかった
準備完了状態:start()メソッドを呼び出し、CPUスケジューリングを待機します
実行ステータス:CPUがリソースを割り当て、run()メソッドを実行した後
スリープ状態:sleep()またはwait()メソッドを呼び出します。スリープ後、準備完了状態に戻り、CPUスケジューリングを待機し続けます。
死亡状態:run()メソッドの実行が完了した後、またはstop()メソッドが手動で呼び出された後[通常、 stop()メソッドは呼び出されません]
// 2019/04/14更新
デーモンスレッド
☞デーモンスレッドとユーザースレッドの違いは、メインスレッドの破壊とともにデーモンスレッドが破壊されることです。
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程i: " + i);
}
}
});
t1.setDaemon(true); //设置为守护线程,和主线程一起销毁
t1.start();
for (int j = 0; j < 5; j++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程j: "+j);
}
System.out.println("主线程执行完毕...");
}
☞効果