线程基础理论

1、创建线程:

       Thread类、Runable接口、Callable带返回值的接口;在使用的时候尽量考虑使用接口实现,因为我们java是单继承多实现;

public class CreateThreadDemo {

     //为何都是使用start()方法 而不是run()方法;因为start方法在创建线程,
     //   run()则是直接调用该方法并没有创建多线程 
     public static void main(String[] args) {
         //1.继承Thread
         Thread thread = new Thread() {
             @Override
             public void run() {
                 System.out.println("继承Thread");
                 super.run();
             }
         };
         thread.start();

         //2.实现runable接口
         Thread thread1 = new Thread(new Runnable() {
             @Override
             public void run() {
                 System.out.println("实现runable接口");
             }
         });
         thread1.start();

         //3.实现callable接口
         ExecutorService service = Executors.newSingleThreadExecutor();
         Future<String> future = service.submit(new Callable() {
             @Override
             public String call() throws Exception {
                 return "通过实现Callable接口";
             }
         });
         try {
             String result = future.get();
             System.out.println(result);
         } catch (InterruptedException e) {
             e.printStackTrace();
         } catch (ExecutionException e) {
             e.printStackTrace();
         }
     }
 }

 

2、线程的状态:

基本概念:

       NEW:调用start()初始状态

       RUNNABLE:运行状态,将就绪和运行称作运行中

       BLOCKED:阻塞,表示线程阻塞于锁

       WAITING:等待状态表示线程进入等待状态,知道通知或中断

       TIMED_WAITING:超时等待状态,在指定时间内自行返回

       TERMINATED:终止状态,线程已执行完毕

线程状态案例

package com.hezm.thread.day1.lifecycle;


import java.util.concurrent.TimeUnit;

public class ThreadStatusDemo {

    /***
     * 查看线程运行状态方法:
     *          1、Recompile  或者run 运行一次程序
     *          2、找到目录target-classes-com....下对应文件ThreadStatusDemo.class 右键 Open in Terminal
     *          3、在console中运行jps  查看当前运行java进程
     *          4、运行jstack 4044     jstack  进程号  查看线程堆栈日志
     *              blocked_thread_2   状态为  TIMED_WAITING
     *              blocked_thread_1   状态为  BLOCKED    锁被线程2抢占,线程1阻塞
     *              wating_thread   状态为  WAITING
     *              time_wating_thread   状态为  TIMED_WAITING
     * @param args
     */
    public static void main(String[] args) {

        new Thread(()->{
            try {
                while (true){
                    TimeUnit.SECONDS.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"time_wating_thread").start();


        new Thread(()->{
            try {
                while (true){
                    synchronized (ThreadStatusDemo.class){
                        //获得锁,然后wait;
                        ThreadStatusDemo.class.wait();
                    }
                }
                //InterruptedException线程可能异常就中断了;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"waiting_Thread").start();

        new Thread(new BlockedDemo(),"blocked_thread_1").start();
        new Thread(new BlockedDemo(),"blocked_thread_2").start();
    }

    //阻塞线程
    static class BlockedDemo extends Thread{
        @Override
        public void run() {
            try {
                while (true){
                    synchronized (ThreadStatusDemo.class){
                        TimeUnit.SECONDS.sleep(100);  
                    }
                }
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

线程状态转换图

 

 

3、线程基本操作:

     join()实现顺序执行

package com.hezm.thread.day1.safe;

/**
 * 实现线程的顺序执行
 */
public class JoinRule {
    static int x = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            x=100;
        });
        t1.start();
        t1.join();
        //值一定为100,在join之后对线程内的操作可见;
        System.out.println(x);
        Thread t2 = new Thread(()->{
            System.out.println("t1");
        });
        Thread t3 = new Thread(()->{
            System.out.println("t2");
        });
        Thread t4 = new Thread(()->{
            System.out.println("t3");
        });
        t2.start();
        t2.join();   // 通过wait方法实现  直到线程被销毁的时候释放;  实现主线程阻塞等待线程执行完成;

        t3.start();
        t3.join();

        t4.start();
        t4.join();


    }
}

 

     线程的优雅中断1:interrupted,实现原理:通过一个volatile修饰的标志位来标识是否中断线程;

package com.hezm.thread.day1.stop;


import java.util.concurrent.TimeUnit;

public class InterruptThread {

    private static int i = 0;

    /***
     * 线程的优雅中断;
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
            //判断是否标记要中断线程: 默认值为false,true表示中断;
            while (!Thread.currentThread().isInterrupted()){    
                i++;
                System.out.println(i);
            }
        });

        thread.start();
        System.out.println(thread.isInterrupted());
        TimeUnit.SECONDS.sleep(1);
        thread.interrupt();  //将 isInterrupted 的值设置为true,标记要进行中断;
        System.out.println(thread.isInterrupted());
        //源码:    private native void interrupt0();
        //jvm方法:  os :: interrupt(Thread thread)
        //     有很多os,针对不同的操作系统有不同的实现;
    }
}

 

    线程复位

package com.hezm.thread.day1.stop;


import java.util.concurrent.TimeUnit;

/**
 * 线程复位:对中断的线程进行中断复位
 *      方式1:Thread.interrupted()
 *      方式2:InterruptedException;   复位的原因:复位标识我得到外界要求中断的信号,然后自己择机中断;
 *      3,为什么所有和阻塞相关的方法都有 InterruptedException 异常?
 *            wait 和 sleep等在阻塞中间可能外部会强行关闭线程,当关闭线程的时候就会抛出 InterruptedException 异常
 *            抛出异常以后就可以进行响应的处理;因此强行关闭,线程并没有死去;
 */
public class ThreadResetDemo {

    //方式1: Thread.currentThread().isInterrupted()
//    public static void main(String[] args) throws InterruptedException {
//        Thread thread = new Thread(()->{
//            //是否为中断?  默认值为false;
//            while (true){
//                if(Thread.currentThread().isInterrupted()){
//                    System.out.println("before:"+Thread.currentThread().isInterrupted());
//                    Thread.interrupted();   //复位回到初始状态
//                    System.out.println("after:"+Thread.currentThread().isInterrupted());
//                }
//            }
//        });
//
//        thread.start();
//        TimeUnit.SECONDS.sleep(1);
//        thread.interrupt();
//    }




    //方式2:InterruptedException,异常的复位
    /**
     * 使用场景:在异常被抓住的时候,我们可以对线程进一步处理;是抛出异常,中断程序或者其他都可以;就
     */
    private static  int i = 0;
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
            //是否为中断?  默认值为false;
            while (!Thread.currentThread().isInterrupted()){
                try {
                    System.out.println(System.currentTimeMillis() + "in Thread");
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    //中断一个处于阻塞状态的线程   join/wait/queue.take;  首先进行复位,然后中断线程;
                    System.out.println(System.currentTimeMillis() + "==c==" + Thread.currentThread().isInterrupted());
                    e.printStackTrace();
                }
                i++;
            }
            System.out.println("i:" + i);
        });
        //  即使主线程启动了TimeUnit.SECONDS.sleep(1)  也会导致thread的 InterruptedException 异常;
        //  因此,休眠前需要将状态进行修改(thread.interrupt())才能体现 InterruptedException 对状态的的修改;
        thread.start();
        System.out.println(System.currentTimeMillis() + "==a==" + thread.isInterrupted());
        thread.interrupt();
        System.out.println(System.currentTimeMillis() + "==b==" + thread.isInterrupted());
        TimeUnit.SECONDS.sleep(1);
    }


}

 

 

 

可重入读写锁的使用

package com.hezm.thread.day1.theory;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**可重入读写锁*/
public class ReentrantReadWriteLockDemo {
    static ReentrantReadWriteLock writeLock = new ReentrantReadWriteLock();    //可重入读写锁;读不需要加锁。
    static Map<String, Object> cacheMap = new HashMap<>();

    static Lock read = writeLock.readLock();
    static Lock write = writeLock.writeLock();

    public static void main(String[] args) {
        /**
         * 适用于:读多写少的场景:
         * 读->读可以共享   // Thread2:在get的时候,  Thread1:线程在get的时候不会阻塞,可共享数据;
         * 读->写互斥   // Thread2:在put的时候,  Thread1:线程在get的时候会阻塞,等待写完才读,读到最新数据;
         * 写->写互斥  // Thread2:在put的时候,  Thread1:线程在put的时候会阻塞,等待写完才put;
         */
        put("zhangsan","23岁");
        get("zhangsan");
    }

    //Thread1:读锁:读的时候获取最新数据
    public static final Object get(String key){
        System.out.println("begin read deta:" + key);
        read.lock();
        try {
            return cacheMap.get(key);
        } finally {
            read.unlock();   //防止死锁,一直不释放锁
        }
    }

    //Thread2:写锁:写操作对读可见
    public static final Object put(String key, Object value){
        write.lock();
        try {
            System.out.println("begin write deta:" + key + "value" + value);
            return cacheMap.put(key,value);
        } finally {
            write.unlock();   //防止死锁,一直不释放锁
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值