2、マルチスレッドの実現方式


1、マルチスレッドの主な実現方式:
一つはThreadクラスを継承しRunnableインタフェースを実現することである
2.Threadクラスの継承とRunnableインタフェースの実現の違い:
  • Javaは単一継承方式であるため、スレッドクラスが他のクラスを継承する場合、Threadクラスを継承する方式は使用できないが、Runnableインタフェースを実現する方式
  • を使用することができる.
  • Threadクラスのrunメソッドは共有できません.例えば、スレッドAはスレッドBのrunメソッドを自分の実行ユニットと見なすことができません.Runnableを使用すると簡単に実現できます.同じRunnableは複数のインスタンスを構築することができるので、一般的にはRunnableはThreadのtask
  • に相当することが理解できます.
  • 職責から言えば、Thread類は主にスレッド自身の関連職責と制御を担当し、Runnableは主にスレッド論理の実行ユニット
  • を担当する.
    3、スレッド実現のすべての方式
  • はThreadクラス
  • を継承する.
  • Runnableインタフェース
  • を実装
  • Callableインタフェースを実現し、FutureTaskにより包装
  • を行う.
  • 匿名内部クラス
  • を使用
  • Lambda式
  • を使用
  • スレッドプール
  • を使用
  • タイマー
  • を使用
    3.1.Threadクラスの継承
    
    public class Thread1 extends Thread {
        @Override
        public void run() {
            System.out.println("  Thread  ");
        }
    
        public static void main(String[] args) {
            Thread1 thread = new Thread1();
            thread.start();
        }
    }
    
    

    3.2、Runnableインタフェースを実現する
    public class Thread2 implements Runnable {
        @Override
        public void run() {
            System.out.println("  Runnable    ");
        }
    
        public static void main(String[] args) {
            Runnable runnable = new Thread2();
            Thread thread2 = new Thread(runnable);
           thread2.start();
        }
    }
    
    
    

    3.3、Callableインタフェースを実現し、FutureTaskで包装する
    public class Thread3 implements Callable {
        @Override
        public String call() throws Exception {
            Thread.sleep(5000);
            return "  Callable  ,   FutureTask  ,    ";
        }
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            Thread3 thread3 = new Thread3();
            FutureTask futureTask = new FutureTask(thread3);
            Thread thread = new Thread(futureTask);
            thread.start();
            System.out.println("      ");
            //           
            String result = (String) futureTask.get();
            System.out.println(result);
        }
    }
    
    

    3.4、匿名内部クラス
    匿名内部クラスにも様々なバリエーションがあり、これら3つの方法は匿名内部クラスを用いて暗黙的にインスタンス化することができる.
    public class Demo{
        public static void main(String[] args) throws Exception {
            //   :Thread     
            new Thread(){
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                }
            }.start();
    
            //   :Runnable     
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                }
            }).start();
    
            ...
        }
    }
    

    匿名の内部クラスの利点は、クラスを追加的に定義する必要がなく、コードの可読性が悪いことです.
    3.5、Lambda式
    public class Demo{
        public static void main(String[] args) throws Exception {
            new Thread(() -> System.out.println("running") ).start() ;
            ...
        }
    }
    

    Runnableは@FunctionalInterface注記で修飾され、インタフェースには1つの方法しかありません.
    3.6、スレッドプール
    public class DemoThreadTask implements Runnable{
        @Override
        public void run() {
            // TODO Auto-generated method stub
            System.out.println("running");
        }
        public static void main(String[] args) {
            DemoThreadTask task = new DemoThreadTask();
            ExecutorService ex = Executors.newCachedThreadPool();
            ex.execute(task);
        }
    }
    
    

    3.7、タイマー
    public class DemoTimmerTask {
        public static void main(String[] args) throws Exception {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate((new TimerTask() {
            @Override
            public void run() {
                System.out.println("    ");
            }
        }), 2000, 1000);
        }
    }
    
    

    TimerTaskはRunnableインタフェースを実現し、Timer内部にはTimerThreadがThreadから継承されている.