线程小知识总结【线程创建、线程优先级、线程安全】

进程历史

在这里插入图片描述在这里插入图片描述

疑问:进程和线程的区别
答:进程是资源分配的最小单位,手握操作系统给他分配的monney,是分包商
线程是CPU调度的最小单位,不持有资源,去请求进程的资源,并消耗资源
进程是抢占处理机的调度单位,拥有内存中虚拟空间
线程属于某个进程,占用该进程的地址空间
疑问:什么是资源?
答:资源信息包括程序段、数据集,所有与进程相关的资源,都被记录在PCB中。
疑问:线程拥有什么?
答:堆栈寄存器、程序计数器和TCB
Java采用单线程编程模型,程序主动创建主线程。
疑问:什么是单线程编程模型
答:不特殊指定,默认是主线程。有耗时操作,放在子线程里。
主线程往往最后执行完毕,最后死掉。
疑问:既然是单线程模型,那JVM是否是单线程模型?
答:JVM实例创建之时,有多线程,如GC、

创建线程

方式1

public class CreateThread {
    public static void main(String[] args) {
        Thread t1 = new Thread();
        Thread t2 = new Thread() {
            @Override
            public void run() {
                System.out.println("==========");
            }
        };
        t1.start();
        t2.start();
        System.out.println(t1.getName());
        System.out.println(t2.getName());

        Thread t3 = new Thread("MyName");
        Thread t4 = new Thread(() -> {
            System.out.println("Runnable...");
        });

        System.out.println(t3.getName());
        System.out.println(t4.getName());

        Thread t5 = new Thread(() -> {
            System.out.println("Runnable..." + Thread.currentThread().getName());
        }, "RunnableThread");

        t5.start();
    }
}

方式2

public class CreateThread2 {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t.start();
//        System.out.println(t.getThreadGroup());
//        System.out.println(Thread.currentThread().getName());
        ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
//        System.out.println(threadGroup.getName());

        System.out.println(threadGroup.activeCount());

        Thread[] threads = new Thread[threadGroup.activeCount()];
        threadGroup.enumerate(threads);

        Arrays.asList(threads).forEach(System.out::println);
    }
}

方式3 主线程

public class CreateThread3 {

    private int i = 0;

    private byte[] bytes = new byte[1024];

    private static int counter = 0;

    //JVM will create a thread named "main"
    public static void main(String[] args) {
        //create a JVM stack
        try {
            add(0);
        } catch (Error e) {
            e.printStackTrace();
            System.out.println(counter);
        }
    }

    private static void add(int i) {
        ++counter;
        add(i + 1);
    }
}

方式4

public class CreateThread4 {

    private static int counter = 1;

    public static void main(String[] args) {

        Thread t1 = new Thread(null, new Runnable() {
            @Override
            public void run() {
                try {
                    add(1);
                } catch (Error e) {
                    System.out.println(counter);
                }
            }

            private void add(int i) {
                counter++;
                add(i + 1);
            }
        }, "Test", 1 << 24);
        t1.start();
    }
}

方式5

public class CreateThread5 {

    private static int counter = 1;

    public static void main(String[] args) {

        try {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                counter++;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            add(1);
                        } catch (Error e) {
//                            System.out.println(counter);
                        }
                    }

                    private void add(int i) {

                        add(i + 1);
                    }
                }).start();
            }
        } catch (Error e) {
            counter++;
        }
        System.out.println("Total created thread nums=>" + counter);
    }
}

Thread的start与run区别

start会创建新的子线程,并启动
run只是Trhead的普通方法调用,仍然在主线程执行。

Thread与Runnable区别

线程设置Daemon、优先级、ID

Daemon线程

public class DaemonThread {

    public static void main(String[] args) throws InterruptedException {

        Thread t = new Thread() {

            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + " running");
                    Thread.sleep(100000);
                    System.out.println(Thread.currentThread().getName() + " done.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }; //new
        t.start();
        t.setDaemon(true);
        //runnable  ->running| ->dead| ->blocked


        Thread.sleep(5_000);   //JDK1.7
        System.out.println(Thread.currentThread().getName());
    }
}

/**
 * A<---------------------------------->B
 *  ->daemonThread(health check)
 * */

Daemon线程2

public class DaemonThread2 {
    public static void main(String[] args) {

        Thread t = new Thread(() -> {
            Thread innerThread = new Thread(() -> {
                try {
                    while (true) {
                        System.out.println("Do some thing for health check.");
                        Thread.sleep(1_000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });

            //innerThread.setDaemon(true);
            innerThread.start();

            try {
                Thread.sleep(1_000);
                System.out.println("T thread finish done.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        //t.setDaemon(true);
        t.start();


    }
}

线程ID、优先级

普通场景

public class ThreadSimpleAPI {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            Optional.of("Hello").ifPresent(System.out::println);
            try {
                Thread.sleep(100000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1");

        t.start();
        Optional.of(t.getName()).ifPresent(System.out::println);
        Optional.of(t.getId()).ifPresent(System.out::println);
        Optional.of(t.getPriority()).ifPresent(System.out::println);
    }
}

实际场景

public class ThreadSimpleAPI2 {

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                Optional.of(Thread.currentThread().getName() + "-Index" + i).ifPresent(System.out::println);
            }
        });
        t1.setPriority(Thread.MAX_PRIORITY);

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                Optional.of(Thread.currentThread().getName() + "-Index" + i).ifPresent(System.out::println);
            }
        });

        t2.setPriority(Thread.NORM_PRIORITY);

        Thread t3 = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                Optional.of(Thread.currentThread().getName() + "-Index" + i).ifPresent(System.out::println);
            }
        });

        t3.setPriority(Thread.MIN_PRIORITY);

        t1.start();
        t2.start();
        t3.start();
    }
}

工具jconsole

线程中断1

public class ThreadClose {
    private static class Worker extends Thread {

        @Override
        public void run() {
            while (true) {
                if (Thread.interrupted())
                    break;
            }
            //-------------
            //-------------
            //-------------
        }
    }

    public static void main(String[] args) {
        Worker worker = new Worker();
        worker.start();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        worker.interrupt();
    }
}

线程中断2

public class ThreadService {

    private Thread executeThread;

    private boolean finished = false;

    public void execute(Runnable task) {
        executeThread = new Thread() {
            @Override
            public void run() {
                Thread runner = new Thread(task);
                runner.setDaemon(true);

                runner.start();
                try {
                    runner.join();
                    finished = true;
                } catch (InterruptedException e) {
                    //e.printStackTrace();
                }
            }
        };

        executeThread.start();
    }

    public void shutdown(long mills) {
        long currentTime = System.currentTimeMillis();
        while (!finished) {
            if ((System.currentTimeMillis() - currentTime) >= mills) {
                System.out.println("任务超时,需要结束他!");
                executeThread.interrupt();
                break;
            }

            try {
                executeThread.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("执行线程被打断!");
                break;
            }
        }

        finished = false;
    }
}

JMM内存模型、线程安全

什么是Java内存模型中的happens-before
Java内存模型JMM
Java内存模型(即JavaMemoryModel,简MM)本身是一种抽象的念,
并不真实存在它描述的是一组规则或规范,通过这组规范定义了程序中各个
变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式·

在这里插入图片描述
JMM中的主内存
-存储」ava实例对象
-声包括成员变量、类信息、常量、静态变量等
-声属于数据共享的区域,多线程并发操作时会引发线程安全问题

JMM与Java内存区域划分是不同的概念层冫欠
-jMM描述的是一组规则,围绕原子性,有序性、可见性展开
-相似点:存在共享区域和私有区域

jMM中的主内存和工作内存
主内存与工亻乍内存的存储类型以及操亻乍方式归纳
-方法里的基本数据举型本地变量将直接存储在工作内存的栈帧结构
-引用类型的本地变量:引用存储在工作内存中,实例存储在主内存
-成员变量、static变量、类信息均会被存储在主内存中
-主内存共享的方式是线程各拷贝删分数据到工作内存,操作完成
后刷新回主内存
在这里插入图片描述

volatile和synchronized的区别

demo实力:

volatile和synchronized的区别
1.vo丨ati|e本质是在告诉」VM当前变量在寄存器(工作内存)中的值是不确
定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前
线程可以访问该变量,其他线程被阻塞住直到该线程完成变量操亻乍为止
2,vo|ati|e仅能使用在变量级别;synchronized则可以使用在变量、方法
和类级别
3.v引ati|e仅能实现变量的修改可见性,不能保证原子性而
syn(hronized则可以保证变量修改的可见性和原子性
4,vo丨ati|e不会造成线程的阻塞,syn(hronized可能会造成线程的阻塞
5.volati|e标记的变量不会被编译器优化,synchronizedfii己的变量可以
被编译器优化

synchronized和lock区别

1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

5)Lock可以提高多个线程进行读操作的效率。

在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

synchronized与线程安全

恰当的合理的上锁,是线程安全的关键

synchronized安全问题的主要诱因
声存在共享数据他称临界资源)
龙存在多条线程共同操作这些共享数据
解决问题的根本方法
同一时刻有且只有一个线程在操作共享数据其他线程必须等到该线
程处理完数据后再对共享数据进行操作

synchronized互斥锁(原子性)的特性
互斥性·即在同一时间只允许一个线程持有某个对象锁,通过这种特性
来实现多线程的协调机制,这样在同一时间只有一个线不寸需要同步的
代码块(复合操作)进行访问。互斥性也称为操作的原子性。
可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后
获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的
值),否贝刂另一个线程可能是在本地缓存的某个副本上继续操作,从而引起不一致。
synchronized锁的不是代码,锁的都是对象

synchronized
根据获取的锁的分类·获取对象锁和获取类锁
获取对象锁的两种用法
1.同步代码块(synchronized(this),synchronized(类实例对
象)),锁是小括号0中的实例对象。
2,同步非静态方法(synchronizedmethod)锁是当前对象的实
例对象。

在这里插入图片描述
疑问:waite与sleep的区别
疑问:线程的生命周期

参考

volatile和synchronized的区别

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章