Javaマルチスレッドとスレッド同期の問題の解決

プロセス:スレッドはプロセスから切り離せません。プロセスとは何かについてお話ししましょう。(エクスプローラーを開くと、現在実行中のプロセスが表示されます)。

スレッド:これは、プロセスおよび実行パス内の単一の順次制御フローです。

シングルスレッド:プロセスに実行パスが1つしかない場合、そのプロセスはシングルスレッドプログラムになります。

マルチスレッド:プロセスに複数の実行パスがある場合、そのプロセスはマルチスレッドプログラムになります。

マルチスレッドを実装する

方式一:继承Thread类
1.定义一个类MyThread 继承Thread类
2.在MyThread类中重写Run()方法
3.创建对象
4.启动线程  用Start方法
public class MyThread extends Thread {
    @Override
    public void run() {
       for (int i=0;i<100;i++){
           System.out.println(i);

       }
    }
}

public class MyThreadDemo {
    public static void main(String[] args) {
        MyThread m1=new MyThread();
        MyThread m2=new MyThread();
        m1.start();
        m2.start();
    }
}
方法2:实现Runnable接口
定义一个MyRunnable类,实现Runnable接口
在MyRunnable类中重写run方法
创建MyRunnable类的对象
创建Thread类对象,将MyRunnable对象作为构造方法的参数
启动线程

public class MyRunnable implements Runnable {
    
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}



public class MyRunnableDemo {
    public static void main(String[] args) {
        MyRunnable my=new MyRunnable();
        Thread t1=new Thread(my);
        Thread t2=new Thread(my);
        t1.start();
        t2.start();
    }

}

質問:なぜrun()メソッドを書き直すのですか?

runメソッドは、スレッドによって実行されるコードをカプセル化するために使用されます。

run()メソッドとstart()メソッドの違いは何ですか?

run():スレッドによって実行されるコードをカプセル化して直接呼び出します。これは、通常のメソッドの呼び出しと同等です。

start():スレッドを開始すると、このスレッドのrun()メソッドがJVMによって呼び出されます。

スレッド名を設定して取得する

   public static void main(String[] args) {
        MyThread m1=new MyThread();
        m1.setName("王");
        String name = m1.getName();
        System.out.println(name);
    }

スレッドスケジューリング

 Javaはプリエンプティブスケジューリングを使用します。優先度の高いスレッドは最初にCPUを使用します。同じ優先順位で、1つがランダムに選択されます。優先度の高いスレッドは、CPUタイムスライスが少し多くなります。

        MyThread m1 = new MyThread();
        MyThread m2 = new MyThread();
        MyThread m3 = new MyThread();
//获取线程的优先级,优先级默认是5,最高是10,最小是1.
//        System.out.println(m1.getPriority());//5
//        System.out.println(m2.getPriority());//5
//        System.out.println(m3.getPriority());//5

//更改线程的优先级
        m1.setPriority(1);
        m2.setPriority(10);
        m3.setPriority(1);

スレッド制御

//Thread.sleep(); 使当前正在执行的线程停留,指定的秒数,然后继续执行。

//vodi join();等待这个线程死亡。
//下面例子,m1,结束后,m2,m3才运行。
        MyThread m1 = new MyThread();
        MyThread m2 = new MyThread();
        MyThread m3 = new MyThread();
 
        m1.setName("王");
        m2.setName("李");
        m3.setName("孙");
   m1.start();
        try {
            m1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        m2.start();
        m3.start();


//void setDaemon(boolean on) 将此线程标记为守护线程,运行的线程都是守护线程时,java虚拟机将退出。
//例子:当主线程刘备结束后,关羽和张飞也退出线程。

        MyThread m1 = new MyThread();
        MyThread m2 = new MyThread();
        
        m1.setName("关羽");
        m2.setName("张飞");
        Thread.currentThread().setName("刘备");
        m1.setDaemon(true);
        m2.setDaemon(true);
        m1.start();
        m2.start();
        for (int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }

スレッドのライフサイクル

 スレッドの同期 

ケース:チケット購入システム、3つのウィンドウが同時にチケットを購入し、複数のスレッドを使用します。

public class SellTicket  implements Runnable{
    private  int tickets=100;
    @Override
    public void run() {
        while(true){
            if (tickets>0){
                try{
                    Thread.sleep(100);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                tickets--;
            }
        }
    }
}

public class SellTickerDmo {
    public static void main(String[] args) {
        SellTicket st=new SellTicket();
        Thread t1=new Thread(st,"窗体1");
        Thread t2=new Thread(st,"窗体2");
        Thread t3=new Thread(st,"窗体3");

        t1.start();
        t2.start();
        t3.start();
    }
}

上記の書き込みは問題を引き起こします、それはチケットであり、何度も販売されています。必要なのは、共有データを操作する複数のステートメントをロックすることです。つまり、それらをロックすると、一度に1つだけがそれらにアクセスできます。

問題を解決するための同期コードブロック方式:

public class SellTicket  implements Runnable{
    private  int tickets=1000;
    private Object obj=new Object();
    @Override
    public void run() {
        while(true){
            //加锁
            synchronized (obj){
            if (tickets>0){
                try{
                    Thread.sleep(10);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                tickets--;
            }
            }
        }
    }
}

同期の問題を解決するためのロック: 

Lockはインターフェースであり、直接インスタンス化して使用することはできません。その実装クラスReentrantLockを使用できます。 

主な方法は、ロックを取得してロックをキャストすることです。

public class SellTicket  implements Runnable{
    private  int tickets=1000;
    private Lock lock =new ReentrantLock();
    @Override
    public void run() {
        while(true){
            try{
                lock.lock();
                if (tickets>0){
                    try{
                        Thread.sleep(10);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"zhang票");
                    tickets--;
                }
            }finally {
                lock.unlock();
            }
        }
    }
}

スレッドセーフクラス:

同期を実行してスレッドの安全性を確保する必要がある場合は、次のクラスを使用できます。それらの基礎となるメソッドはすべて、synchronizedでロックされてい ます。

        StringBuffer sbf=new StringBuffer(); 
//下面这两个是线程安全的集合,但是我们一般不会去用。用下面的方法转!
        Vector ve=new Vector();
        Hashtable ht=new Hashtable();

//下面方法可以把集合转成 线程安全的。
List<String> list = Collections.synchronizedList(new ArrayList<String>());

 

おすすめ

転載: blog.csdn.net/weixin_44126152/article/details/106373872