一、基础概念

CPU核心数和线程数的关系

核心数:线程数=1:1 ;使用了超线程技术后---> 1:2

CPU时间片轮转机制

又称RR调度,会导致上下文切换

什么是进程和线程

进程:程序运行资源分配的最小单位,进程内部有多个线程,会共享这个进程的资源
线程:CPU调度的最小单位,必须依赖进程而存在。

澄清并行和并发

并行:同一时刻,可以同时处理事情的能力
并发:与单位时间相关,在单位时间内可以处理事情的能力

高并发编程的意义、好处和注意事项

好处:充分利用cpu的资源、加快用户响应的时间,程序模块化,异步化
问题:
线程共享资源,存在冲突;
容易导致死锁;
启用太多的线程,就有搞垮机器的可能

二、认识java里的线程

创建线程的三种方式:

  • 继承Thread类

  • 实现runable接口

  • 实现callable接口,允许有返回值

package com.enjoy.demo.p1.ch1.class1;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @Author: BillYu
 * @Description:三种方式创建线程
 * @Date: Created in 14:56 2019-02-19.
 */
public class NewThread {
    /**
     *  拓展自Thread类
     */
    private static class UseThread extends Thread{
        @Override
        public void run() {
            System.out.println("I am extends Thread");
        }
    }

    /**
     * 实现Runable接口
     */
    private static class UseRun implements Runnable{
        @Override
        public void run() {
            System.out.println("I am implements Runable");
        }
    }

    /**
     * 实现Callable接口,允许有返回值
     */
    private static class UseCall implements Callable<String>{
        @Override
        public String call() throws Exception {
            System.out.println("I am implements Callable");
            return "CallResult";
        }
    }


    public static void main(String[] args) throws InterruptedException, ExecutionException {
        UseThread useThread = new UseThread();
        useThread.start();

        UseRun useRun = new UseRun();
        new Thread(useRun).start();
        Thread t = new Thread(useRun);
//        方法启用且不释放资源
//        t.stop();


        //java线程是协作式
        //interrupt()中断一个线程,并不是强行关闭这个线程,打个招呼,中断标志位置为true
        //isInterrupted()判定当前线程是否处于中断状态
        //interrupted判定但钱是否处于中断状态,中断标志位置为false
        t.interrupt();

        UseCall useCall = new UseCall();
        FutureTask<String> futureTask = new FutureTask<>(useCall);
        new Thread(futureTask).start();
        System.out.println(futureTask.get());

    }
}

安全终止线程

怎么样才能让Java里的线程安全停止工作呢
线程自然终止:自然执行完或抛出未处理异常
stop(),resume(),suspend()已不建议使用,stop()会导致线程不会正确释放资源,suspend()容易导致死锁。
java线程是协作式,而非抢占式
调用一个线程的interrupt() 方法中断一个线程,并不是强行关闭这个线程,只是跟这个线程打个招呼,将线程的中断标志位置为true,线程是否中断,由线程本身决定。
isInterrupted() 判定当前线程是否处于中断状态。

package com.enjoy.demo.p1.ch1.class1;

/**
 * @Author: BillYu
 * @Description:如何安全中断线程
 * @Date: Created in 15:47 2019-02-19.
 */
public class EndThread {
    private static class UseThread extends Thread{
        public UseThread(String name){
            super(name);
        }

        @Override
        public void run() {
            String threadName = Thread.currentThread().getName();
            while (!isInterrupted()){
                System.out.println(threadName+" is run");
            }
            System.out.println(threadName+" interrput flag is "+isInterrupted());
        }
    }


    public static void main(String[] args) throws InterruptedException{
        Thread endThread = new UseThread("endThread");
        endThread.start();
        Thread.sleep(20);
        endThread.interrupt();

    }



}

static方法interrupted() 判定当前线程是否处于中断状态,同时中断标志位改为false。
方法里如果抛出InterruptedException,线程的中断标志位会被复位成false,如果确实是需要中断线程,要求我们自己在catch语句块里再次调用interrupt()。

package com.enjoy.demo.p1.ch1.class1;

/**
 * @Author: BillYu
 * @Description: 更改打断标记
 * @Date: Created in 16:56 2019-02-19.
 */
public class HasInterruptedException {
    private static class UseThread extends Thread{
        public UseThread(String name){
            super(name);
        }
        @Override
        public void run(){
            String threadName = Thread.currentThread().getName();
            while (!isInterrupted()){
                try{
                    Thread.sleep(100);
                }catch (InterruptedException e){
                    System.out.println(threadName+" interput flag is "+isInterrupted());
                    //**
                    interrupt();
                    e.printStackTrace();
                }
                System.out.println(threadName);
            }
            System.out.println(threadName+" interput flag is "+isInterrupted());

        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread endThread = new UseThread("HashInterrputEx");
        endThread.start();
        Thread.sleep(500);
        endThread.interrupt();
    }
}

三、更多了解

线程常用方法和线程的状态

线程只有5种状态。整个生命周期就是这几种状态的切换。创建、就绪、运行、阻塞、消亡
image.png
run()和start() :run方法就是普通对象的普通方法,只有调用了start()后,Java才会将线程对象和操作系统中实际的线程进行映射,再来执行run方法。
yield() :让出cpu的执行权,将线程从运行转到可运行状态,但是下个时间片,该线程依然有可能被再次选中运行。

线程的优先级

取值为1~10,缺省为5,但线程的优先级不可靠,不建议作为线程开发时候的手段

守护线程

和主线程共死,finally不能保证一定执行

package com.enjoy.demo.p1.ch1.class1;

import java.util.concurrent.ExecutionException;

/**
 * @Author: BillYu
 * @Description:守护线程
 * @Date: Created in 14:44 2019-02-20.
 */
public class DaemonThread {
    private static class UseThread extends Thread{
        @Override
        public void run() {

            //alt+shift+z
            try {
                while (!isInterrupted()){
                    System.out.println(Thread.currentThread().getName()
                    +" I am extends Thread.");
                }
                System.out.println(Thread.currentThread().getName()
                +" interrupt flag is "+ isInterrupted());
            } finally {
                System.out.println("=======> finally");
            }
        }

        public static void main(String[] args) throws InterruptedException, ExecutionException {
            UseThread useThread = new UseThread();
            //设置为守护线程 ,和主线程共死,和finally不能保证一定执行
            useThread.setDaemon(true);
            useThread.start();
            Thread.sleep(5);
//            useThread.interrupt();

        }
    }

}