线程的基本概念

进程

假设硬盘上有一个简单的程序,这个程序叫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次后,升级为重量级锁,重量级锁就是去操作系统那里去申请资源

原文地址:https://www.cnblogs.com/striver20/p/13718686.html