美文网首页
Java 线程基础

Java 线程基础

作者: Tinyspot | 来源:发表于2022-09-01 06:44 被阅读0次

1. 进程 vs 线程

  • 进程:正在运行的程序,是资源分配的最小单位(基本单位)
  • 线程是CPU调度的最小单位
    • 轻量级进程
    • 进程中的一条执行路径,是 CPU 的基本调度单位
  • 一个进程由一个或多个线程组成,彼此间完成不同的工作,同时执行,称为多线程
  • 一台设备能并行执行多少个线程取决于CPU核心数

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

1.1 线程的特点

  • 线程抢占式执行
  • 在单核 CPU 中,宏观上同时执行,微观上顺序执行

1.2 并发与并行

  • 并发指一个 CPU 同时处理多个任务(轮流使用 CPU 时间片)
  • 并行是指多个 CPU 或多核 CPU 同时处理多个不同的任务

2. 创建线程

  • 在 JDK 中代表线程的就只有 Thread 类
  • 线程的执行单元是 run(),可以通过继承 Thread 然后重写 run() 实现,也可以实现 Runnable 接口

准确地讲,创建线程只有一种方式那就是构造 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();

匿名内部类方式:

  • 子类重写父类的 run()
  • 语法 new 父类() { 子类内容 }; 匿名类是一个表达式,因此在定义的最后用分号;结束
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

  • Runnable 的 run() 无返回值
  • Callable 的 call() 有返回值,并且有声明异常
public interface Runnable {
    public abstract void run();
}
public interface Callable<V> {
    V call() throws Exception;
}

3.2 Future 接口

  • 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;
        }
    }
}

相关文章

  • 技术体系

    一,java核心 java基础,jvm,算法,多线程,设计模式 Java基础:java基础相关,全栈java基础 ...

  • Java多线程目录

    Java多线程目录 Java多线程1 线程基础Java多线程2 多个线程之间共享数据Java多线程3 原子性操作类...

  • android 多线程 — 线程的面试题和答案

    这里都是我从各个地方找来的资料,鸣谢: Java多线程干货系列—(一)Java多线程基础 JAVA多线程和并发基础...

  • Android中的多线程

    1. Java多线程基础 Java多线程,线程同步,线程通讯 2. Android常用线程 HandlerThre...

  • Java基础

    Java基础 集合基础 集合框架 多线程基础 多线程框架 反射 代理 集合基础 ArrayList LinkedL...

  • java多线程相关

    (一) 基础篇 01.Java多线程系列--“基础篇”01之 基本概念 02.Java多线程系列--“基础篇”02...

  • java线程入门基础(二)

    java线程入门基础(二) 一、认识Java里的线程 1.1 Java里的程序天生就是多线程的 一个Java程序从...

  • Java多线程高级特性(JDK8)

    [TOC] 一、Java多线程 1.Java多线程基础知识 Java 给多线程编程提供了内置的支持。一条线程指的是...

  • 高并发Java

    高并发Java(1):前言 高并发Java(2):多线程基础 高并发Java(3):Java内存模型和线程安全 高...

  • Java-并发编程知识点总结

    目录: 线程基础 线程池 各种各样的锁 并发容器 原子类 Java 内存模型 线程协作 AQS 框架 一、线程基础...

网友评论

      本文标题:Java 线程基础

      本文链接:https://www.haomeiwen.com/subject/inhztltx.html