public class MyThread extends Thread {
    // 多个线程无法共享线程类的实例变量
    private int i;
    
    @override
    public void run() {
        // 线程需要完成的任务
        // run()方法是一个普通方法
        ...
    }
}
public static void main(String[] args) {
    MyThread t = new MyThread();
    // 首先启动了线程,然后由jvm去调用该线程的run()方法
    t.start();
}public class MyThread implements Runnable {
    // 创建多个线程可以共享线程类的实例变量
    // 因为程序创建的Runnable对象只是线程的target,而多个线程可以共享一个target,所以多个线程可以共享一个实例变量
    private int i;
    
    @override
    public void run() {
        // 线程需要完成的任务
        ...
    }
}
public static void main(String[] args) {
    MyThread mt = new MyThread();
    Thread t = new Thread(mt, "myThread");
    t.start();
}看起来和Runnable很像,但call方法可以有返回值、可以抛出异常。
public class MyThread implements Callable<Integer> {
    private int i;
    
    @override
    public Integer call() throws Exception {
        // 线程执行体,具有返回值
        ...
    }
}
public static void main(String[] args) {
    MyThread mt = new MyThread();
    FutureTask<Integer> ft = new FutureTask<>(mt);
    Thread t = new Thread(ft, "myThread");
    t.start();
    
    // 获取执行结束后的返回值
    try {
        ft.get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
}Java5提供了Future接口来代表Callable接口的call方法的返回值,并为Future接口提供了一个FutureTask实现类,FutureTask实现了Future接口和Runnable接口——可以作为Thread的target。
Future提供了三种功能:判断任务是否完成;能够中断任务;能够获取任务执行结果。
底层实现异步原理:在客户端请求的时候,直接返回客户端需要的数据(此数据不一定完整,只是简单的一点不耗时的操作),但是客户端并不一定马上使用所有的信息,此时就有了时间去完善客户需要的信息
与FutureTask的区别和联系:future是个接口,futuretask可以通过实现该接口,调用get方法返回执行结果
Runnable、Callable的优势在于——线程类只是实现了Runnable或Callable接口,还可以继承其它类;在这种方法下,多个线程可以共享一个target对象,因此非常适合多个相同线程处理同一份资源的情况,从而将CPU、代码和数据分开,形参清晰的模型,体现了面对对象的编程思想。
劣势在于编程复杂度略高。
在Java中有两类线程:User Thread用户线程、Daemon Thread守护线程
只要当前JVM实例中尚存在一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。
Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是GC。当我们的程序中不再有任何运行的Thread,程序就不会再产生垃圾,垃圾回收器也就无事可做,所以当垃圾回收线程是JVM上仅剩的线程时,垃圾回收线程会自动离开。它始终在低级别的状态中运行,用于实时监控和管理系统中的可回收资源。
不是所有的任务都可以分配给Daemon来进行服务,比如读写操作或者计算逻辑就不可以,因为一旦User退出了,可能大量数据还没有来得及读入或写出。
守护线程并非只有虚拟机内部提供,用户在编写程序时也可以自己设置守护线程。
Thread daemonThread = new Thread();
// 设定 daemonThread 为守护线程,default false(非守护线程)
// 必须在thread.start()之前设置,否则会抛出一个IllegalThreadStateException异常。
daemonThread.setDaemon(true);
// 验证当前线程是否为守护线程,返回 true 则为守护线程
System.out.println(daemonThread.isDaemon());在Daemon线程中产生的新线程也是Daemon的。
RE判断程序执行结束的标准是所有的非守护执线程行完毕,而不管守护线程的状态。
线程则是JVM级别的,如果你在Web 应用中启动一个线程,这个线程的生命周期并不会和Web应用程序保持同步。也就是说,即使你停止了Web应用,这个线程依旧是活跃的。正是因为这个很隐晦的问题,所以很多有经验的开发者不太赞成在Web应用中私自启动线程。
Spring为JDK Timer和Quartz Scheduler所提供的TimerFactoryBean和SchedulerFactoryBean能够和Spring容器的生命周期关联,在 Spring容器启动时启动调度器,而在Spring容器关闭时,停止调度器。所以在Spring中通过这两个FactoryBean配置调度器,再从 Spring IoC中获取调度器引用进行任务调度将不会出现这种Web容器关闭而任务依然运行的问题。而如果你在程序中直接使用Timer或Scheduler,如不 进行额外的处理,将会出现这一问题。
CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再次加载这个任务的状态,从任务保存到再加载的过程就是一次上下文切换。

线程的调度策略采用抢占式,优先级高的线程比优先级低的线程优先执行。
    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;
 
   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;
 
    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;    pubilc final void setPriority(int newPriority);
    public final int getPriority();线程调度器负责为runnable状态线程分配cpu时间。
(我选择学习并发的时候再深入。。。)

一个访问共用资源的程序片段,这些共用资源无法同时被多个线程访问
互斥量的本质就是一把锁,在访问共享资源前对互斥量进行设置(加锁),在访问完成后释放(解锁)互斥量。对互斥量加锁以后,任何其他试图再次对互斥量加锁的线程都会被阻塞知道线程释放该互斥量。
使用volatile来修饰一个信号量控制线程的中断。
class MyThread implements Runnable {
    private volatile boolean stopMark = false;
    
    @Override
    public void run() {
        System.out.println("thread start");
        while(!stopMark) {
            try {
                Thread.sleep(500);  //模拟一个耗时的方法
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("thread stop");
    }
    
    public void stop() {
        this.stopMark=true;
    }
}选择器epoll()?NIO?
无状态对象一定是线程安全的。
不可变对象一定是线程安全的
放到容器里再说~
volatile一般用在多个线程访问同一变量时,对该变量进行唯一性约束,volatile保证了变量的可见性,不能保证原子性。
private volatile booleanflag = false;保证变量的可见性:volatile本质是告诉JVM当前变量在线程寄存器(工作内存)中的值是不确定的,需要从主存中读取,每个线程对该变量的修改是可见的,当有线程修改该变量时,会立即同步到主存中,其他线程读取的是修改后的最新值。
不能保证原子性:原子性指的是不会被线程调度机制打断的操作,在java中,对基本数据类型的变量的读取和赋值操作是原子性操作。自增/自减操作不是原子性操作。例如:i++,其实是分成三步来操作的:1)从主存中读取i的值;2)执行+1操作;3)回写i的值。volatile关键字并不能保证原子性操作。非原子操作都会产生线程安全的问题。
内置锁synchronized(以Class对象为锁)
该关键字能够保证代码块的同步性和方法层面的同步。
重入(粒度为线程)
不适用多个相互约束变量
AtomicInteger atomicInteger = new AtomicInteger();
atomicInteger.getAndIncrement();    //实现原子自增
atomicInteger.getAndDecrement();    //实现原子自减synchronized(this){
      value++;
}private Lock lock = new ReentrantLock();
private final int incrementAndGet(){
    lock.lock();
    try {
        return value++;
    } finally {
        // TODO: handle finally clause
        lock.unlock();
    }
}原文:https://www.cnblogs.com/angelica-duhurica/p/11429501.html