JUC 之线程创建

2023-11-12  本文已影响0人  Tinyspot

1. 线程类Thread

在 JDK 中代表线程的就只有 Thread 类
准确地讲,创建线程只有一种方式那就是构造 Thread 类,而实现线程的执行单元则有两种方式,第一种是重写 Thread 的 run(), 第二种是实现 Runnable 接口的 run(), 并且将 Runnable 实例用作构造 Thread 的参数

1.1 java.lang.Thread

public class Thread implements Runnable {
    // 线程名字
    private volatile String name;
    private int            priority;
    // 线程的唯一标识符
    private long tid;

    private Runnable target;
    private ThreadGroup group;

    // 线程的执行单元 run()
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
}

1.2 创建线程的两种方式

2. 继承 Thread 类

@Slf4j
public class MyThread extends Thread {
    /**
     * this.getId() 和 this.getName() 有局限性,必须 extends Thread 才能使用,因为这是父类中的方法
     */
    @Override
    public void run() {
        log.info("线程id: " + this.getId() + "; 线程名称: " + this.getName());
        log.info("Thread name: " + Thread.currentThread().getName());
    }
}

调用

@Test
public void run() {
    MyThread thread = new MyThread();
    thread.start();
}

打印结果:

18:29:28.230 [Thread-1] INFO juc.MyThread - 线程id: 14; 线程名称: Thread-1
18:29:28.235 [Thread-1] INFO juc.MyThread - Thread name: Thread-1

2.2 匿名内部类方式

例如:通过匿名类方式创建线程

@Test
public void run() {
    Thread thread = new Thread() {
        // 子类重写父类的run()
        @Override
        public void run() {
            log.info("run...");
        }
    };
    thread.start();
}

打印结果:

18:39:39.258 [Thread-1] INFO juc.JUCDemo - run...

也可写成如下:

@Test
public void run() {
    new Thread() {
        @Override
        public void run(){
            log.info("run...");
        }
    }.start();
}

2.3 其他方式:将线程对象作为构造参数

@Test
public void run() {
    MyThread myThread = new MyThread();
    Thread thread = new Thread(myThread);
    thread.start();
}

3. 实现 Runnable 接口

@Slf4j
public class MyThread implements Runnable {
    @Override
    public void run() {
        log.info("run...");
    }
}

调用

@Test
public void run() {
    MyThread myThread = new MyThread();
    // 创建线程对象
    Thread thread = new Thread(myThread, "test");
    thread.start();
}

打印结果:

18:33:39.150 [test] INFO juc.MyThread - run...

3.2 匿名内部类方式

@Test
public void run() {
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            log.info("run...");
        }
    };
    Thread thread = new Thread(runnable);
    Thread thread2= new Thread(runnable, "t2");

    thread.start();
    thread2.start();
}

打印结果:

18:37:00.045 [Thread-1] INFO juc.JUCDemo - run...
18:37:00.045 [t2] INFO juc.JUCDemo - run...

4. 实现 Callable 接口

@Test
public void run() {
    Callable<Integer> callable = new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            return Stream.iterate(1, n -> n + 1)
                    .limit(100)
                    .reduce(0, Integer::sum);
        }
    };

    // Callable 有返回值,需要 FutureTask 来接收执行结果
    FutureTask<Integer> task = new FutureTask<>(callable);
    new Thread(task).start();

    Integer result = null;
    try {
        // 接收运行的结果: get()是阻塞的,等call()执行完才会返回
        result = task.get();
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    System.out.println(result);
}

5. Runable vs Callable

public interface Runnable {
    public abstract void run();
}
public interface Callable<V> {
    V call() throws Exception;
}

6. 其他

6.1 设置线程名称

方式一:直接 setName()

MyThread thread = new MyThread();
thread.start();
thread.setName("Thread name");

方式二:在构造方法里设置

public class MyThread extends Thread {
    public MyThread(String name) {
        super(name);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读