Java 线程基础

2022-09-01  本文已影响0人  Tinyspot

1. 进程 vs 线程

例如:Java 虚拟机是一个进程,当中默认包含主线程(main),可通过代码创建多个独立线程,与 main 并发执行

1.1 线程的特点

1.2 并发与并行

2. 创建线程

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

2.1 示例一:继承 Thread

public class MyThread extends Thread {
    @Override
    public void run() {
      // // this.getId() 和 this.getName() 有局限性,必须是 extends Thread 才能使用,因为这是父类中的方法
      System.out.println("线程id: " + this.getId() + "; 线程name: " + this.getName() + "; Thread name: " + Thread.currentThread().getName());
    }
}
MyThread thread = new MyThread();
thread.start();

匿名内部类方式:

new Thread() {
    @Override
    public void run(){
        System.out.println("threa start...");
    }
}.start();

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

public static void main(String[] args) {
    MyThread myThread = new MyThread();
    Thread thread = new Thread(myThread);
    thread.start();
}

2.2 示例二:实现 Runnable

MyThread myThread = new MyThread();
// 创建线程对象
Thread thread = new Thread(myThread, "Thread name");
thread.start();

public class MyThread implements Runnable {
    @Override
    public void run() {
        System.out.println("run...");
    }
}

匿名内部类方式

public static void main(String[] args) {
    Runnable runnable = new Runnable() {
        @Override
        public void run() { // ... }
    };
    Thread thread = new Thread(runnable);
    Thread thread2= new Thread(runnable, "t2");

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

2.3 示例三:实现 Callable(Since: 1.5)

public static void main(String[] args) throws Exception {
    Callable<Integer> callable = new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            int sum = 0;
            for (int i = 0; i <= 100; i++) {
                sum += i;
            }
            return sum;
        }
    };

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

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

3. Runable / Callable / Future

3.1 Runable vs Callable

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

3.2 Future 接口

public interface Future<V> {
    // get() 以阻塞形式等待 Future 中的异步处理结果
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)  throws InterruptedException, ExecutionException, TimeoutException;
}
public class FutureTask<V> implements RunnableFuture<V> {
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }
}

public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

4. 其他

4.1 设置线程名称

直接 setName() 或者 在构造方法里设置

// 方式一:直接 setName()
MyThread thread = new MyThread();
thread.start();
thread.setName("Thread name");

// 方式二:使用构造方法
public class MyThread extends Thread {
    public MyThread(String name) {
        super(name);
    }
}

4.2 将 Callable 放入线程池执行

public class Demo {
    public void test() throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        Callable<Integer> caller = new Caller(10);
        Future<Integer> future = executorService.submit(caller);
        System.out.println(future.get());
        executorService.shutdown();
    }

    class Caller implements Callable<Integer> {
        private Integer sum = 0;

        public Caller(Integer sum) {
            this.sum = sum;
        }

        @Override
        public Integer call() throws Exception {
            for (int i = 0; i <= 100; i++) {
                sum += i;
            }
            return sum;
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读