————————示例代码见文末——————

线程创建

  v1、Runnable实现接口
  v1_1、继承Thread类
  v1_2、匿名内部类创建线程

线程通信

V2、sleep(100)
    1、Thread类里的静态方法
    2、睡眠时间毫秒
    3、不释放所在线程锁
v2_1、wait()
    1、java.lang.Object类里的非静态方法
    2、wait()调用后,释放调用wait对象的线程锁,
       如果对象不占用锁则报IllegalMonitorStateException
	3、无参 则会一直等直到 notify()或notifyAll()    
    4、wait(100) 单位毫秒 超时自动被唤醒
v2_2、notify()     
	1、java.lang.Object类里的非静态方法
    2、notify()调用后,通知同一个线程锁下wait(),继续往下执行
    3、notifyAll()调用后,通知所有线程锁下wait(),继续往下执行   	  
v2_3、join()
    1、Thread类里的非静态方法
    2、a.join() 等待a线程执行完毕再接着执行a.join()所在的线程
    3、main{ a.start();b.start();a.join();}
      main线程先开启了A,B线程,B线程执行不受a.join影响的 
      只是说主线程等待A执行完再执行,B线程是独立的不受影响的 
 v2_4、Interrupt()
      1、Thread的非静态方法
      2、thread.interrupt();//设置中断标志位为true
      3、sleep() wait() join() 不断检测线程的中断位 
         如果中断为true报InterruptedException 如果false不处理  
      4、抛出InterruptedException 清除中断标志位
         即设置中断标志位为false  
 v2_5、yield()
     1、Thread的静态方法 
     2、线程 从运行状态--到就绪状态
     3、线程在 this.start()准备执行——就绪状态run()运行——就是运行状态           
 v2_6、对象调用wait()(疑惑-在对象是一个线程的前提下,
       线程开启再调用调用wait,不会起到等待的效果)
       
	  if(对象==类实例 && 类实例.start()){
			wait()等待的是类实例run方法执行完
	  }else {//!类实例.start() || 对象!=类实例
		    wait()等待所在线程
      } //TODO 代码运行总结的不知道对不对 
  v2_7、sleep()和wait()区别  
      1、wait()等待释放锁
      2、sleep()等待不释放锁

线程关键字

v3、volatile
主要总结 volatile修饰 线程私有变量改变主内存立即改变,
        没有修饰线程私有变量改变等线程结束主内存改变
   内存模型的相关概念
     cup——》   cache
     cup——》   cache|| -----》 总线锁或者缓存一致性协议----> 主存
     cup——》   cache
   并发编程中的三个概念
     原子性 即一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
     可见性  可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值 
     有序性  即程序执行的顺序按照代码的先后顺序执行
   volatile具有可见性不具有原子性 
   常用场景:
	   1.状态标记量
	   2.double check
v3_1、AtomicInteger  原子性变量
v3_2、ThreadLocal    线程本地变量——每个线程有自己独立的变量
v3_3、验证volatile不具备原子性 
     COUNT++不具备原子性COUNT从主内存复制然后+1 
     在执行+1这个操作的时候主内又被复制出去了一份 导致COUNT没有保证原子性

线程锁

 v4、synchronized 
    Class类的所有对象的锁
        锁类、锁类的静态代码块、静态属性、
    单个对象的锁
        锁对像、锁非静态代码块、锁非静态属性
  v4_1、Lock
     Lock 接口 ReentrantLock实现类
     lock.lock();
     lock.unlock();
     lock如果定义在线程自己的方法类,则只是锁自己的线程并不能保证多个线程同步执行

线程池

FutureTask
Future是一个接口,代表可以取消的任务,并可以获得任务的执行结果
FutureTask 是基本的实现了Future和runnable接口
实现runnable接口,说明可以把FutureTask实例传入到Thread中,在一个新的线程中执行。

=========================================
欢迎指正交流 欢迎指正交流 欢迎指正交流 欢迎指正交流 欢迎指正交流

/**
 * Runnable
 * 实现接口创建线程
 * */
public class V1 implements Runnable {
    @Override
    public void run() {
        System.out.println("hello");
    }

    public static void main(String[] args) {
        Thread  thread = new Thread(new V1());
        thread.start();
    }
}
/**
 * Thread
 * 继承实现创建线程
 * */
public class V1_1 extends Thread {

    public void run() {
        System.out.println("hello");
    }

    public static void main(String[] args) {
        V1_1 v1_1 = new V1_1();
        v1_1.start();
    }
}
/**
 * Thread
 * 继承实现创建线程
 * */
public class V1_1 extends Thread {

    public void run() {
        System.out.println("hello");
    }

    public static void main(String[] args) {
        V1_1 v1_1 = new V1_1();
        v1_1.start();
    }
}
/**
 *匿名内部类创建线程
 * */
public class V1_2 {

    public static void main(String[] args) {
        new Thread(new Runnable() {
            public void run() {
                System.out.println("hello");
            }
        }).start();

        //jdk1.8
        new Thread( () -> {System.out.println("hello1");} ).start();
    }
}
/**
 * sleep(100)
 *      1、Thread类里的静态方法
 *      2、睡眠时间毫秒
 *      3、不释放所在线程锁
 */
public class V2 {
    private static  final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss SSS");

    public static void main(String[] args) {
        System.out.println(df.format(new Date()));
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(df.format(new Date()));
    }
}
/**
 * wait()
 *      1、java.lang.Object类里的非静态方法
 *      2、wait()调用后,释放调用wait对象的线程锁,如果对象不占用锁则报IllegalMonitorStateException
 *      3、无参 则会一直等直到 notify()或notifyAll()
 *      4、wait(100) 单位毫秒 超时自动被唤醒
 */
public class V2_1 {

    public static void main(String[] args) {
      //new V2_1().wait(); 直接调用会报IllegalMonitorStateException

//        V2_1.class 有锁,但是v2_11没有锁所以也会报IllegalMonitorStateException
//        synchronized (V2_1.class){
//            System.out.println(Thread.currentThread().getName());
//            try {
//                V2_1 v2_11 = new V2_1();
//                v2_11.wait();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        }
        V2_1 v2_1 = new V2_1();
        synchronized (v2_1){
            System.out.println(Thread.currentThread().getName());
            try {
                v2_1.wait(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
/**
 * notify()
 *      1、java.lang.Object类里的非静态方法
 *      2、notify()调用后,通知同一个线程锁下wait(),继续往下执行
 *      3、notifyAll()调用后,通知所有线程锁下wait(),继续往下执行
 */
public class V2_2 extends Thread{
    private static  Boolean BOOLEAN = true;

    public void run() {
        synchronized (V2_2.class){
            if(BOOLEAN){
                try {
                    System.out.println("wait start");
                    V2_2.class.wait();
                    System.out.println("wait end");
                } catch (InterruptedException e) {

                }
            }else {
                System.out.println("notify start");
                V2_2.class.notify();
                System.out.println("notify end");
            }
        }
    }
    // 以BOOLEAN为锁,BOOLEAN重新赋值后为一个新的对象,所以无法唤醒BOOLEAN.wait()等待
//    public void run() {
        synchronized (BOOLEAN){
            if(BOOLEAN){
                try {
                    System.out.println("wait start");
                    BOOLEAN.wait();
                    System.out.println("wait end");
                } catch (InterruptedException e) {

                }
            }else {
                System.out.println("notify start");
                BOOLEAN.notify();
                System.out.println("notify end");
            }
        }
    }


    public static void main(String[] args) throws InterruptedException {
        V2_2 v2_2 = new V2_2();
        V2_2 v2_3 = new V2_2();
        v2_2.start();
        sleep(10);
        BOOLEAN = false;
        v2_3.start();


    }
}

/**
 * join()
 *  1、Thread类里的非静态方法
 *  2、a.join() 等待a线程执行完毕再接着执行a.join()所在的线程
 *  3、main线程先开启了,A,B线程,B线程执行不受a.join影响的 只是说主线程等待A执行完再执行,B线程是独立的不受影响的
 */
public class V2_3 {

    public static void main(String[] args) throws InterruptedException {
        Thread a = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("start A");
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("end A");
            }
        });
        Thread b = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("start B");
                try {
                    sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("end B");
            }
        });
        a.start();
        b.start();
        a.join();
        b.join();
        System.out.println("end");
    }
}
/**
 * Interrupt()
 *      1、Thread的非静态方法
 *      2、thread.interrupt();//设置中断标志位为true
 *      3、sleep() wait() join() 不断检测线程的中断位 如果中断为true报InterruptedException 如果false不处理
 *      4、抛出InterruptedException 清除中断标志位即设置中断标志位为false
 *      5、thread.isInterrupted()  获取中断标志位的结果
 */
public class V2_4 extends Thread{
    public static Object lock = new Object();

    @Override
    public void run() {
        System.out.println("start");
        synchronized (lock) {
            try {
                lock.wait();//sleep wait join  不断检测线程的中断位 如果中断为true报InterruptedException 如果false不处理
            } catch (InterruptedException e) {//清除中断标志位即设置中断标志位为false
                System.out.println(Thread.currentThread().isInterrupted());//获取中断标志位的结果
                Thread.currentThread().interrupt(); //设置中断标志位为true
                System.out.println(Thread.currentThread().isInterrupted());//获取中断标志位的结果
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Thread thread = new V2_4();
        thread.start();
        try {
            sleep(2000);
        } catch (InterruptedException e) {
        }
        thread.interrupt();//设置中断标志位为true
    }
}

/**
 * yield()
 *     Thread的静态方法
 *     线程 从运行状态--到就绪状态
 *     线程在 this.start()准备执行——就绪状态 ,run()运行——就是运行状态
 */
public class V2_5 extends Thread{
        @Override
        public void run() {
            for (int i = 1; i <= 50; i++) {
                System.out.println(this.getName() + "  " + i);
                // 当i为30时,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行)
                if (i == 30) {
                    this.yield();
                }
            }
        }

        public static void main(String[] args) {
            V2_5 yt1 = new V2_5();
            V2_5 yt2 = new V2_5();
            yt1.start();
            yt2.start();
        }
}

/**
 * 对象调用wait()
 * if(对象==类实例 && 类实例.start()){
 *     wait()等待的是类实例run方法执行完
 * }else {//!类实例.start() || 对象!=类实例
 *    wait()等待所在线程
 * } TODO 代码运行总结的不知道对不对
 *
 */
public class V2_6 extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " run ");
        }

        public static void main(String[] args) throws InterruptedException {
            V2_6 V2_6 = new V2_6();
            synchronized(V2_6) {
                try {
                    System.out.println(Thread.currentThread().getName()+" start t1");
                  V2_6.start(); //开启和注释验证
                    System.out.println(Thread.currentThread().getName()+" wait()");
                    V2_6.wait();
                    System.out.println(Thread.currentThread().getName()+" continue");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

}
/**
 * sleep()和wait()区别
 *      1、wait()等待释放锁
 *      2、sleep()等待不释放锁
 */
public class V2_7 extends Thread{
    private static Object object = new Object();

    @Override
    public void run() {
       waitV2_7(1);
       // sleepV2_7(1);
    }

    private void waitV2_7(Object object){
        synchronized (object){
            System.out.println("wait");
            try {
                object.wait(1000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void sleepV2_7(Object object){
        synchronized (object){
            try {
                System.out.println("sleep");
                this.sleep(1000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        V2_7 v2_7 = new V2_7();
        V2_7 v2_8 = new V2_7();
        V2_7 v2_9 = new V2_7();

        v2_7.start();
        v2_8.start();
        v2_9.start();
    }
}
/**
 * volatile
 *  内存模型的相关概念
 *    cup   cache
 *    cup   cache        总线锁或者缓存一致性协议    主存
 *    cup   cache
 * 并发编程中的三个概念
 *    原子性   即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
 *    可见性  可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值  V41
 *    有序性  即程序执行的顺序按照代码的先后顺序执行
 *  volatile  可见性     原子性 AtomicInteger  Lock  synchronized 保证i++的原子性
 *  常用场景:
 *     1.状态标记量
 *     2.double check
 *详见:https://wwwblogs/dolphin0520/p/3920373.html  5volatile使用场景
 *
 *-----------------------------------------------------------------------------------------------------------------------------
 *    //每开启一个线程  从主内存复制变量到线程的私有工作空间  主线程是 stop = false    A:stop = false    B:stop = false
 *   //没有volatile修饰  B线程将stop =true因为B线程还没有结束所以主内存还是stop = false 当B线程执行完毕更新主内存stop =true 接着A结束
 *   //有volatile修饰  B线程将stop =true 立即将主内存的stop =true 接着A结束,接着B执行
 *
 *   //主内存改变每个子线程就会同步改变  子线程改变如果不是volatile则必须等待子线程完毕才会改变主内存,如果volatile修饰就会立即改变主内存
 *   //没有volatile修饰时子线程改变变量主线程为什么不会变,  因为如果有多个子线程都改变则主内存不知道用哪个才正确
 *   没有volatile修饰stop
 *主要事件                    主               私有线程A             私有线程B
 *
 *stop = false
 *
 *开启A,B线程             stop = false          拷贝stop = false       拷贝stop = false
 *
 *stop = false           stop = false          stop = true;这时候B还没有结束
 *
 * stop = true            stop = true            B结束
 *
 *有volatile修饰stop
 *主要事件                    主               私有线程A             私有线程B
 *
 *stop = false
 *
 *开启A,B线程             stop = false          拷贝stop = false       拷贝stop = false
 *
 *stop = flase           stop = flase          stop = true;这时候B还没有结束但是只要改变主内存同步改变
 *
 *stop = true            stop = true
 *主要总结volatile修饰 线程私有变量改变主内存立即改变,没有修饰线程私有变量改变等线程结束主内存改变
 *
 * 下面例子证明 volatile他有可见性
 */
public class V3  {
//    private static   volatile  boolean stop = false;
      private static   boolean stop = false;

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!stop){
                    System.out.println("等待主内存改变");
                }
                System.out.println("线程A结束");
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                stop =true;
                try {
                    sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程B结束");
            }
        }).start();
    }
}

/**
 * AtomicInteger
 *      原子性变量
 */
public class V3_1 {
    private static  AtomicInteger atomicInteger = new AtomicInteger(0);

    public static void main(String[] args)  {
        for (int i = 0; i < 100; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    atomicInteger.incrementAndGet();
                }
            }).start();
        }
        try {
            sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(atomicInteger);
    }
}

/**
 * ThreadLocal
 *     线程本地变量——每个线程有自己独立的变量
 */
public class V3_2 {
    private static ThreadLocal threadLocal = new ThreadLocal();
//    private static Integer integer= 0;

    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    threadLocal.set(i);
//                    integer=i;
                    try {
                        sleep(30);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(threadLocal.get()+"_"+Thread.currentThread().getName());
//                    System.out.println(integer+"_"+Thread.currentThread().getName());
                }

            }
        },"thread");

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 200; i < 300; i++) {
                    threadLocal.set(i);
//                    integer=i;
                    try {
                        sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(threadLocal.get()+"_"+Thread.currentThread().getName());
//                    System.out.println(integer+"_"+Thread.currentThread().getName());
                }

            }
        },"thread1");
        thread.start();
        thread1.start();
    }

}
/**
 * 验证volatile不具备原子性
 * COUNT++不具备原子性 COUNT从主内存复制然后+1 在执行+1这个操作的时候主内又被复制出去了一份 导致COUNT没有保证原子性
 */
public class V3_3 {
    private static volatile  int COUNT = 0;

    public static void main(String[] args)  {
        for (int i = 0; i < 100; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    COUNT++;
                }
            }).start();
        }
        try {
            sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(COUNT);
    }
}
/**
 * synchronized
 */
public class V4 {
    private static Object o = new Object();
    static V4 lock = new V4();

    // lock on dynamic method
    public synchronized void dynamicMethod() {
        System.out.println("dynamic method");
        sleepSilently(2000);
    }

    // lock on static method
    public static synchronized void staticMethod() {
        System.out.println("static method");
        sleepSilently(2000);
    }

    // lock on this
    public void thisBlock() {
        synchronized (this) {
            System.out.println("this block");
            sleepSilently(2000);
        }
    }

    // lock on an object
    public void objectBlock() {
        synchronized (o) {
            System.out.println("dynamic block");
            sleepSilently(2000);
        }
    }

    // lock on the class
    public static void classBlock() {
        synchronized (V6.class) {
            System.out.println("static block");
            sleepSilently(2000);
        }
    }

    private static void sleepSilently(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        // object lock test
        new Thread() {
            @Override
            public void run() {
                lock.dynamicMethod();
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                lock.thisBlock();
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                lock.objectBlock();
            }
        }.start();

        sleepSilently(3000);
        System.out.println();

        // class lock test
        new Thread() {
            @Override
            public void run() {
                lock.staticMethod();
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                lock.classBlock();
            }
        }.start();

    }
}
/**
 * Lock
 *    Lock 接口 ReentrantLock实现类
 *    lock.lock();
 *    lock.unlock();
 *    lock如果定义在线程自己的方法类,则只是锁自己的线程并不能保证多个线程同步执行
 */
public class V4_1 {
    private ArrayList<Integer> arrayList = new ArrayList<Integer>();
    private Lock lock = new ReentrantLock();    //注意这个地方
    public static void main(String[] args)  {
        final V4_1 test = new V4_1();
        for (int i = 0; i < 3; i++) {
            new Thread(){
                public void run() {
                    test.insert(Thread.currentThread());
                };
            }.start();
        }
    }

    public void insert(Thread thread) {
//      Lock lock = new ReentrantLock();    //加在这里不保证外面开启多线程同步
        lock.lock();
        try {
            System.out.println(thread.getName()+"得到了锁");
            for(int i=0;i<5;i++) {
                arrayList.add(i);
            }
        } catch (Exception e) {
        }finally {
            System.out.println(thread.getName()+"释放了锁");
            lock.unlock();
        }
    }
}
/**
 * FutureTask
 *
 Future是一个接口,代表可以取消的任务,并可以获得任务的执行结果

 FutureTask 是基本的实现了Future和runnable接口
 实现runnable接口,说明可以把FutureTask实例传入到Thread中,在一个新的线程中执行。
 实现Future接口,说明可以从FutureTask中通过get取到任务的返回结果,也可以取消任务执行(通过interreput中断)
 * //从1+10000000000
 */
public class V5 {
    private static final Long  LENGTH = 1000000000L;
    private static final Long  AREA = 10000000L;

    public static void main(String[] args) {

        V5 inst=new V5();
        // 创建任务集合
        List<FutureTask<Long>> taskList = new ArrayList<FutureTask<Long>>();
        // 创建线程池
        ExecutorService exec = Executors.newFixedThreadPool(5);
        for (long i = 0; i < LENGTH/AREA; i++) {
            // 传入Callable对象创建FutureTask对象
            FutureTask<Long> ft = new FutureTask<Long>(inst.new ComputeTask(i*AREA,(i+1)*AREA));
            taskList.add(ft);
            // 提交给线程池执行任务,也可以通过exec.invokeAll(taskList)一次性提交所有任务;
            exec.submit(ft);
        }

        System.out.println("所有计算任务提交完毕, 主线程接着干其他事情!");

        // 开始统计各计算线程计算结果
        Long totalResult = 0L;
        for (FutureTask<Long> ft : taskList) {
            try {
                //FutureTask的get方法会自动阻塞,直到获取计算结果为止
                totalResult = totalResult + ft.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }

        // 关闭线程池
        exec.shutdown();
        System.out.println("多任务计算后的总结果是:" + totalResult);

    }

    private class ComputeTask implements Callable<Long> {
        private Long start;
        private Long end;

        public ComputeTask(Long start, Long end){
            this.start = start;
            this.end = end;
        }

        @Override
        public Long call() throws Exception {
            Long result =0L;
           for (Long i =  start; i<end;i++){
               result = result+i;
           }
            return result;
        }
    }
}

更多推荐

线程之菜鸟教程