다시 배우는 자바 동시성을 - 호기심 GET 스레드를 생성하는 방법은 여러 가지가 결국 알고?

오라클 공식 문서는 스레드를 만들 수 있습니다

  • Java SE 8 API文档: docs.oracle.com/javase/8/do...

    java.lang.Thread의 클래스 문서를 참조하십시오.

    1. 이 클래스는 스레드의 서브 클래스로 선언하고 실행 메소드를 오버라이드 (override)됩니다.

    官方原话: 실행의 새 스레드를 생성하는 방법은 두 가지가 있습니다. 하나의 서브 클래스로 클래스를 선언하는 것입니다 Thread. 이 서브 클래스는, 오버라이드 (override) 할 필요가 run클래스의 방법을 Thread.

    /**
     * 实现线程的第一个方式 继承Thread
     * @author yiren
     */
    public class MyThread extends Thread {
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " Thread running...");
        }
    
        public static void main(String[] args) throws IOException {
            new MyThread().start();
            System.in.read();
        }
    }
    
    
    
    复制代码
    1. 실행 가능한 인터페이스를 달성하고 run 메소드를 구현합니다.

    官方原话: 스레드를 만들 수있는 다른 방법은 클래스가 구현하는 것을 선언하는 Runnable인터페이스를. 그 클래스는 그 구현 run방법을.

/**
 * 实现线程的第二个方式 实现Runnable接口
 * @author yiren
 */
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " Runnable running...");
    }

    public static void main(String[] args) throws IOException {
        new Thread(new MyRunnable()).start();
        System.in.read();
    }
}

复制代码

두 개의 머리 방법의 장점과 단점

    1. 코드의 구조를 고려까지, 작업 특정 스레드 실행 방법은 코드를 실행하는 것입니다, 코드는 비즈니스에 해당, 그것은 분리와 우리의 스레드를 생성해야한다.
    2. 상속하는 경우 Thread, 비동기 작업을 구축 할 때마다, 우리는 별도의 스레드를 설정해야합니다. 그리고 스레드 소비를 만드는 것은 당신이 사용하는 경우, 비교적 큰 Runnable, 우리는 크게 스레드를 생성하기 위해 손실과 파괴를 줄일 수 있습니다 스레드 풀, 같은 도구를 잘 사용을 얻을 수 있습니다. 리소스 절약.
    3. 자바 상속 단일 상속이기 때문에 Thread수업 후, 당신은 크게 확장 성을 제한하는 다른 클래스에서 상속 할 수 없습니다.
    /* What will be run. */
    private Runnable target;

		public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

		private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null, true);
    }
		
		private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        ......
        
        this.target = target;
        
      	......
    }

		@Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
复制代码
  • 두 가지 방법의 특성 (위의 Thread 클래스의 소스 코드 참조)

    • 상속은 Thread전체한다 run()방법을 재정의
    • 달성 Runnable궁극적으로 방법입니다 호출Runnableruntarget.run()
  • 두 방법은 그것의 효과 일 무슨 경우?

    /**
     * @author yiren
     */
    public class MyThreadAndRunnable {
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " runnable running...");
                }
            }
            ) {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " thread running...");
                }
            };
    
            // 这个地方应该是执行重写Thread类的run方法中的逻辑!
            thread.start();
        }
    }
    复制代码
    • 물론, 위의 오버라이드 (override)하지 않는다고 말했다 방법은 호출 그것을 다시 할 전화가없는 경우, a는.Threadrun()target.run()target.run()
  • 정확하게, 한 방향으로 만 스레드를 생성하고, 그 빌드로되는 Thread(가) 위의 두 말을하는 것입니다, 두 가지 방법이 있습니다, 스레드 실행 유닛을 클래스, 달성한다.

다른 버전 :

  • 스레드 풀 스레드를 생성

    /**
     * wrong 线程池创建
     *
     * @author yiren
     */
    public class ThreadPoolExample {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newCachedThreadPool();
            for (int i = 0; i < 1000; i++) {
                executorService.submit(() -> {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName());
                });
            }
        }
    }
    
    // Executors中的DefaultThreadFactory 
    static class DefaultThreadFactory implements ThreadFactory {
            private static final AtomicInteger poolNumber = new AtomicInteger(1);
            private final ThreadGroup group;
            private final AtomicInteger threadNumber = new AtomicInteger(1);
            private final String namePrefix;
    
            DefaultThreadFactory() {
                SecurityManager s = System.getSecurityManager();
                group = (s != null) ? s.getThreadGroup() :
                                      Thread.currentThread().getThreadGroup();
                namePrefix = "pool-" +
                              poolNumber.getAndIncrement() +
                             "-thread-";
            }
    
            public Thread newThread(Runnable r) {
                Thread t = new Thread(group, r,
                                      namePrefix + threadNumber.getAndIncrement(),
                                      0);
                if (t.isDaemon())
                    t.setDaemon(false);
                if (t.getPriority() != Thread.NORM_PRIORITY)
                    t.setPriority(Thread.NORM_PRIORITY);
                return t;
            }
        }
    复制代码
    • newThread()알려진 방법, 심지어 스레드 풀은, 본질적으로의 사용이다 Thread스레드를 생성.
  • 호출 및 FutureTask는 스레드를 만들

  • 상기 UML은, 스레드와의 Runnable 내부에서 본 또는 실제로 달성하는 데 사용하는 도면.

  • 타이머 타이머

    
    /**
     * @author yiren
     */
    public class TimerExample {
        public static void main(String[] args) {
            Timer timer = new Timer();
            // 每隔1s打印下自己的名字
            timer.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " timer running...");
                }
            }, 1000, 1000);
        }
    }
    复制代码
    • 그것은 실제로 실행 가능한 인터페이스를 구현 TimerTask를, 당신은 볼 수 TimerTask이 추상 클래스
  • 익명 내부 클래스 람다 식 (본질은 동일)

    /**
     * 匿名内部类
     * @author yiren
     */
    public class AnonymousInnerClassExample {
        public static void main(String[] args) {
            new Thread() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                }
            }.start();
    
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName());
                }
            }).start();
    
        }
    }
    
    /**
     * lambda表达式
     * @author yiren
     */
    public class LambdaExample {
        public static void main(String[] args) {
            new Thread(() -> System.out.println(Thread.currentThread().getName())).start();
        }
    }
    复制代码

내 소개

  • 항주, 일반 학부 독서, 컴퓨터 과학 및 기술 전문 지식, 20 년 졸업 좌표.
  • 주로 Golang, 쉘에 대해 쓸 것, 자바 개발을하고. 마이크로 서비스, 빅 데이터는이 방향으로 할 준비, 관심.
  • 당신 족장 스프레이에 불 루키 단계에 현재, 미친 동생이 배우고있다.
  • 메시지 교환을 떠나 오신 것을 환영합니다! ! !

추천

출처juejin.im/post/5e3f9669e51d4526cb160ee9