• 线程的基本概念


    进程

    假设硬盘上有一个简单的程序,这个程序叫QQ.exe,这个程序是一个静态的概念,当你双击它,弹出一个界面登陆进去,这时候叫做一个进程。进程相对于一个程序来说它是一个动态的概念。

    线程

    作为一个进程里面最小的执行单元他叫一个线程,用简单的话讲一个程序里不同的执行路径就叫做一个线程。

    创建多线程方法1、继承Thread类,重写run()方法,调用start开启线程

    package com.sun.test;
    
    public class TestThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 200; i++) {
                System.out.println("world");
            }
        }
    
        public static void main(String[] args) {
            TestThread testThread = new TestThread();
            testThread.start();
            for (int i = 0; i < 200; i++) {
                System.out.println("hello");
            }
        }
    }
    
    

    创建多线程方法2、实现runnable,重写run方法

    package com.sun.test;
    
    public class TestThread1 implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 200; i++) {
                System.out.println("world");
            }
        }
        public static void main(String[] args) {
            TestThread1 testThread1 = new TestThread1();
            new Thread(testThread1).start();
            for (int i = 0; i < 200; i++) {
                System.out.println("hello");
            }
        }
    
    }
    
    

    创建多线程方法3、从线程池启动

    启动线程

    1. new Thread().start();

    2. new Threas(Runnable).start;

    3. 从线程池启动

      线程里面的方法

      sleep:当前线程暂停一段时间让给别的线程去执行。

      Yield:当前线程正在执行的时候停下来进入等待队列。

      join:自己在当前线程加入你调用Join的线程,本线程等待。等调用的线程运行完了,自己再去执行。

      常见的线程状态

      • 新建状态

      • Ready就绪状态

      • Running运行状态

      • Teminated结束状态

      • Waiting等待状态

      • Blocked阻塞状态

        synchronized

    public class T {
        private int count = 10;
        private object o = new object();
        public void m() {
            synchronized(o){ //任何线程要想执行下面的代码,必须先拿到o的锁
                count--;
                System.out.println(Thread.currentThread().getName()+"count="+count);
            }
        }
    }
    

    如果每次都定义一个锁的对象Object o 把它new出来那加锁的时候太麻烦每次都要new一个新的对象出来,所以有一个简单的方式就是synchronize(this)锁定当前对象就行。

    public class T {
        private int count = 10
        public void m() {
            synchronized(this){ //任何线程要想执行下面的代码,必须先拿到this的锁
                count--;
                System.out.println(Thread.currentThread().getName()+"count="+count);
            }
        }
    }
    
    public class T {
        private int count = 10;
        public synchronized void m() { //等同于synchronize(this)
                count--;
                System.out.println(Thread.currentThread().getName()+"count="+count);
        }
    }
    

    synchronized保证了原子性,有保证了可见性

    synchronized锁的是对象而不是代码,锁方法锁锁的是this,锁static方法锁的是class,锁方法和非锁方法是可以同时执行的,锁升级从偏向锁到自旋锁到重量级锁。

    synchronized:系统自带、系统自动加锁、自动解锁、不可以出现多个不同的等待队列、默认进行四种锁状态升级

    执行时间短,线程数少,用自旋

    执行时间多,线程数多,用系统锁

    偏向锁:记录这个线程ID
    自旋锁:如果线程争用,就升级为自旋锁(线程数量少)
    重量级锁:10次(线程数量多)

    锁升级的过程

    当我们使用synchronized的时候HotSpot实现:上来之后第一个去访问某把锁的线程,比如sync(Object),来了之后先在这个Object的头上面markdown记录这个线程(如果只有第一个线程访问的时候实际上是没有给这个Object加锁的,在内部实现的时候,只是记录线程的ID(偏向锁))。

    偏向锁如果有线程争用的话,就升级为自旋锁。

    自旋锁转圈10次后,升级为重量级锁,重量级锁就是去操作系统那里去申请资源

  • 相关阅读:
    Struts2完全解耦和
    storm 错误汇总
    sublime3 在ubuntu下不能输入中文
    sublime3 10款必备插件
    sublime3 SublimeREPL python3
    sublime3 Package Control不能使用
    Buffer ByteBuffer 缓冲区
    redis cluster批量插入
    延期执行的方案计策略汇总
    linux 免密登录
  • 原文地址:https://www.cnblogs.com/striver20/p/13718686.html
Copyright © 2020-2023  润新知