1.基本的な概念
プログラム:命令とデータの順序付けられたコレクションであり、操作上の意味はなく、静的な概念です。
プロセス:プログラムを実行する実行プロセスであり、動的な概念です。これは、システムリソース割り当ての単位です。
通常、プロセスには複数のスレッドを含めることができます。スレッドはCPUのスケジューリングと実行の単位です。
多くのマルチスレッドがシミュレートされます。実際のマルチスレッドとは、複数のCPU、つまりサーバーなどの複数のコアを指します。
マルチスレッドのシミュレーション、つまり1つのCPUの場合、CPUは同時に1つのコードしか実行できず、切り替えが速いため、同時実行されているように見えます。
スレッドは独立した実行パスです。
プログラムの実行中は、自分でスレッドを作成しなくても、バックグラウンドでメインスレッドやgcスレッドなどの複数のスレッドが存在します。main
()はメインスレッドと呼ばれ、システムの入り口であり、実行に使用されます。プログラム全体:
プロセスでは、複数のスレッドが開かれている場合、実行中のスレッドはスケジューラによってスケジュールされます。スケジューラは
オペレーティングシステムと密接に関連しており、シーケンスを人為的に妨害することはできません。
同じリソースで操作する場合、リソースの取得の問題があり、同時実行制御を追加する必要があります。
スレッドは、CPUスケジューリング時間や同時実行制御オーバーヘッドなどの追加のオーバーヘッドをもたらします。
各スレッドは独自の作業メモリで相互作用します。不適切なメモリ制御はデータの不整合を引き起こします
2.マルチスレッドを実現する3つの方法
最初のメソッド:Threadクラスを継承し、runメソッドを書き直します(理解してください)
実装コードは次のとおりです。
//创建多线程方式一:继承Thread类,重写run方法,调用start方法开启线程
public class TestThread1 extends Thread{
@Override
public void run(){
for (int i = 0; i < 1000; i++) {
System.out.println("看代码--"+i);
}
}
public static void main(String[] args) {
//main线程,主线程
//创建线程对象,并调用start()方法启动线程
TestThread1 thread1 = new TestThread1();
thread1.start();
for (int i = 0; i < 1000; i++) {
System.out.println("学习多线程--"+i);
}
}
}
2番目の方法:Runnableインターフェースを実装し、runメソッドを書き直します(強調)
実装コードは次のとおりです。
//创建多线程方式二:实现Runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
public class TestThread2 implements Runnable{
@Override
public void run(){
for (int i = 0; i < 1000; i++) {
System.out.println("看代码--"+i);
}
}
public static void main(String[] args) {
//main线程,主线程
//创建Runnable接口的实现类对象
TestThread2 testThread2 = new TestThread2();
//创建线程对象,通过线程对象来开启我们的线程,代理
Thread thread = new Thread(testThread2);
thread.start();
for (int i = 0; i < 1000; i++) {
System.out.println("学习多线程--"+i);
}
}
}
3番目のメソッド:Callableインターフェースを実装するには(理解できる)
、Callableインターフェースを実装し、戻り値の型を
書き換え、callメソッドをスローし、
ターゲットオブジェクトを
作成し、実行サービスを作成する必要があります。ExecutorService ser = Executors.newFixedThreadPool(1);
実行のために送信: Futureresult1 = ser.submit(t1);
結果を取得します:boolean r1 = result1.get()
サービスをシャットダウンします:ser.shutdownNow();
コードの練習-亀とウサギ:
//模拟龟兔赛跑
public class Race implements Runnable{
//定义胜利者
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
//模拟兔子休息。每隔10毫秒
if (Thread.currentThread().getName().equals("兔子") && i%10==0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//判断比赛是否结束
boolean flag = gameOver(i);
if(flag)
break;
System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
}
}
//判断是否完成比赛
private boolean gameOver(int steps){
if(winner != null) //已经有winner了
return true;
if(steps == 100){
winner = Thread.currentThread().getName();
System.out.println("winner is "+ winner);
return true;
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
3.スレッドメソッド
setPriority(int newPriority)
スレッドの優先度を変更します。
static void sleep(long millis)
現在実行中のスレッドを指定されたミリ秒の間スリープ状態にします。
void join()
スレッドが終了するまで待ちます。
static void yield()
現在実行中のスレッドオブジェクトを一時停止し、他のスレッドを実行
void interrupt()
します。スレッドを中断します。これを使用して
boolean isAlive()
、スレッドがアクティブかどうかをテストしないでください。
テストスレッドの優先順位(priority)
複数の実行の結果によると、メインスレッドが毎回最初に実行されます。そして、他の3つはランダムに
知られています。メインスレッドの優先度は5、未設定(デフォルト)も5です。低優先度は呼び出される可能性が低いだけであり、低優先度が呼び出されないということではなく、すべてCPUスケジューリングに依存します。
コード演習:
package com.lu.state;
//测试线程优先级
//根据多次运行结果:main线程每次是都是最先运行。而另外3个,随机
//可知:main线程优先级是5,不设置(默认)也是5。优先级低只是被调用的概率低,
//并不是优先级低就不会被调用了,这都要看CPU的调度
public class TestPriority{
public static void main(String[] args) {
//主线程默认优先级
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread t0 = new Thread(myPriority);
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
//先设置优先级在启动
t1.setPriority(1);
t2.setPriority(10);
t1.start();
t2.start();
t0.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
}
}
デーモンスレッド
スレッドは、ユーザースレッドとデーモンスレッドに分けられます。
仮想マシンは、ユーザースレッドが実行されることを確認する必要があります。
仮想マシンは、デーモンスレッドの実行を待つ必要はありません。たとえば
、バックグラウンドで操作ログを記録し、メモリを監視し、ガベージコレクションを待ちます。
コード演習:
package com.lu.state;
//测试守护线程
//上帝守护你
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true);//默认是false,表示是用户线程,正常的线程都是用户线程...
thread.start();//上帝守护线程启动
new Thread(you).start();//你,用户线程启动
}
}
//上帝
class God implements Runnable{
@Override
public void run() {
while (true){
System.out.println("上帝保佑着你");
}
}
}
//你
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你一生都开心的活着");
}
System.out.println("goodbye world!");
}
}