メインスレッド: メインメソッドを実行するスレッドをメインスレッドと呼びます
シングルスレッドプログラム: プログラムはmaniから上から順に実行されます
プログラムはメインメソッドから実行されます。 JVM はメインメソッドを実行し、それを見つけます オペレーティングシステム
CPU への実行パスを開きます
CPU はこのパスを通じてメインメソッドを実行できます
このパスにはメインスレッドという名前が付いています
スレッドメソッドを作成します1. Thread クラスを継承する
実装手順:
1. Thread クラスのサブクラスを作成する
2. Thread クラスの run メソッドを書き換え、スレッドのタスクを設定する
3. Thread クラスのサブクラス オブジェクトを作成する
4. Thread クラスの start メソッドを呼び出して新しいスレッドを開始し、run メソッド
を実行してスレッドの実行を開始します。Java 仮想マシンはスレッドの run メソッドを呼び出します。
その結果、現在のスレッド (メインスレッド) ともう一方のスレッド (run メソッドを実行するスレッド) の 2 つのスレッドが同時に実行されます。
スレッドを複数回開始することは違法です。特に、スレッドの実行が終了した場合、再起動することはできません。
印刷結果にはランダム性があります:
2 つのスレッドを開いて、CPU に適したものを選択してください
1 public class MyThread extends Thread{ 2 /* 3 * 2.重写Thread类中的run方法,设置线程的任务 4 * 开启这个线程要干什么事情 5 */ 6 @Override 7 public void run() { 8 for (int i = 0; i < 50; i++) { 9 System.out.println("run..."+i);10 }11 }12 }13 public static void main(String[] args) {14 //3.创建Thread类的子类对象15 MyThread mt = new MyThread();16 //mt.run();//不会开启线程,还是单线程程序17 //4.调用Thread类中的start方法开启一个新的线程,执行run方法18 mt.start();19 20 new MyThread().start();21 22 for (int i = 0; i < 50; i++) {23 System.out.println("main..."+i);24 }25 }
スレッドの名前:
メインスレッド: " main"
開いている他のスレッドの名前: "Thread-0"、"Thread-1"....
スレッドの名前を取得します
1. Thread クラスのメソッド getName
String getName() はスレッドの名前を返しますスレッド 。
2. 現在実行中のスレッドを取得する Thread クラスの static メソッド
static Thread currentThread() は、現在実行中のスレッド オブジェクトへの参照を返します。
スレッドの名前を設定します。
1. Thread クラスのメソッド setName(String name)
void setName(String name) は、パラメータ名と同じになるようにスレッド名を変更します。
2. サブクラスにパラメーター化されたコンストラクターを追加し、親クラス Thread クラスのパラメーター化されたコンストラクターを呼び出し、スレッドの名前を渡し、親クラスにスレッドの名前を付けます (父親が息子に名前を付けます)
Thread(String name ) 新しい Thread オブジェクトを割り当てます。
実装手順:
1. Runnableインターフェースの実装クラスを作成します
2. Runnableインターフェースのrunメソッドをオーバーライドし、スレッドタスクを設定します
3. 実装クラスを作成しますRunnableインターフェースのオブジェクト
4. Threadクラスのオブジェクトを作成し、コンストラクター
Thread(Runnableターゲット)にRunnableインターフェースの実装クラスを渡して、新しいThreadオブジェクトを割り当てます。
Runnable を実装する利点
1. クラスが Thread クラスを継承した後は、他のクラスを継承できないという事実を回避します (単一継承の制限)
2. スレッドタスクの設定はスレッドの開始から切り離されており、スケーラビリティが向上します
実装クラスの役割はスレッドタスクを設定することです
Thread クラスの役割: スレッドを開始することです
スレッドの匿名の内部クラスが使用されます
匿名: no name
内部クラス: 他のクラスの内部に書かれたクラス(メンバーの位置: メンバーの内部クラス、ローカルの位置( inメソッド): ローカル内部クラス)
匿名内部クラスの形式:
新しい親クラス/インターフェイス(){
親クラス/インターフェイスのメソッドをオーバーライドします;
};
マルチスレッド親クラス:
Thread
1 new Thread(){2 //重写run方法,设置线程任务3 @Override4 public void run() {5 for (int i = 0; i < 20; i++) {6 System.out.println(Thread.currentThread().getName()+":"+i);7 }8 }9 }
上記のヒープ コードは、サブクラスを作成し、親クラスのメソッドを書き換えるプロセスです
プログラムにはスレッド セーフティの問題があります: 重複したチケットと存在しないチケットが存在します。 sold
解決策:
1 つ目の方法: 同期されたコード ブロック
を使用できます (ロック オブジェクト) {
共有データにアクセスするコード;
}
注:
は、複数のスレッドで使用されています 同じロック オブジェクトです
//メンバーの位置にロック オブジェクトを作成します (一意であることが保証されています)
1 Object obj = new Object(); 2 3 @Override 4 public void run() { 5 //让卖票重复执行 6 while(true){ 7 8 * 同步代码块 9 * 程序会频繁的判断锁,获取锁,释放锁,所以会降低速度10 11 synchronized (obj) {12 if(ticket>0){13 //为了提高安全问题的概率,让程序睡眠14 try {15 Thread.sleep(10);16 } catch (InterruptedException e) {17 e.printStackTrace();18 }19 //卖票ticket--20 System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票");21 }22 }23 }24 }プログラムにはスレッド セーフティの問題があります: 重複したチケットや存在しないチケットが販売されます
解決策:
2 番目のメソッド: 同期メソッド
使用手順:
1. セキュリティ上の問題を引き起こす可能性のあるコードをメソッドに抽出します
2. メソッドに同期されたキーワードを追加します
修飾子 synchronized 戻り値の型 メソッド名 (パラメータ) {
セキュリティ上の問題がある可能性のあるコード;
共有データにアクセスするコード;
}
同期メソッドで使用されるロック オブジェクトは何ですか?
使用されるのはこのクラス オブジェクトです new RunnableImpl()-->Call this
Static同期メソッド、どのロックオブジェクトが使用されていますか?
使用されているのは、このクラスオブジェクトのクラス属性(リフレクション)です
RunnableImpl.class
1 *@Override 2 public void run() { 3 //让卖票重复执行 4 while(true){ 5 payTicket2(); 6 } 7 } 8 9 10 * 静态的同步方法11 12 public static synchronized void payTicket2(){13 synchronized (RunnableImpl.class) {14 if(ticket>0){15 //为了提高安全问题的概率,让程序睡眠16 try {17 Thread.sleep(10);18 } catch (InterruptedException e) {19 e.printStackTrace();20 }21 //卖票ticket--22 System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票");23 }24 }25 }26 27 28 29 * 抽取出一个同步方法30 * 快捷键:alt+shift+m31 32 public ynchronized void payTicket1() {33 synchronized (this) {34 //System.out.println(this);//cn.itcsat.demo10.RunnableImpl@6706435 if(ticket>0){36 //为了提高安全问题的概率,让程序睡眠37 try {38 Thread.sleep(10);39 } catch (InterruptedException e) {40 e.printStackTrace();41 }42 //卖票ticket--43 System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票");44 }45 }46 }
程序出现了线程安全问题:卖了重复的票和不存在的票
*
* 解决方案:
* 第三种方式:使用Lock接口,JDK1.5之后出现的
*
* java.util.concurrent.locks.Lock接口
* 方法:
* void lock() 获取锁。
* void unlock() 释放锁。
* 接口的实现类:ReentrantLock
*
* 实现步骤:
* 1.在成员位置创建一个Lock接口的实现类对象ReentrantLock
* 2.在可能出现线程安全问题的代码前,调用lock方法获取锁
* 3.在可能出现线程安全问题的代码后,调用unlock方法释放锁
*
*1.在成员位置创建一个Lock接口的实现类对象ReentrantLock
Lock l = new ReentrantLock();
1 @Override 2 public void run() { 3 //让卖票重复执行 4 while(true){ 5 //2.在可能出现线程安全问题的代码前,调用lock方法获取锁 6 l.lock(); 7 if(ticket>0){ 8 //为了提高安全问题的概率,让程序睡眠 9 try {10 Thread.sleep(10);11 //卖票ticket--12 System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票");13 } catch (InterruptedException e) {14 e.printStackTrace();15 }finally {16 //3.在可能出现线程安全问题的代码后,调用unlock方法释放锁17 l.unlock(); 18 }19 }20 }
以上がスレッド、スレッド作成例チュートリアルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。