Wilson

自强不息 厚德载物

深入Java线程(一)

线程是系统调度的最小单元,一个进程可以包含多个线程,作为任务的真正运作者,有自己的栈(Stack)、寄存器(Register)、本地存储(Thread Local)等,但是会和进程内其他线程共享文件描述符、虚拟地址空间等。在具体实现中,线程还分为内核线程、用户线程,Java 的线程实现其实是与虚拟机相关的。
###创建线程方式

  • 继承Thread

    public class ThreadImpl extends Thread {   
    }
    
  • 实现Runable
    ```
    public class MyThread implements Runnable {
    private int ticket;
    private Lock lock = new ReentrantLock();

    public MyThread(int ticket) {
    this.ticket = ticket;
    }

    @Override
    public void run() {
    print();
    }

    public void print() {
    lock.lock();
    try {
    while (ticket > 0) {
    System.out.println(“ticket==” + ticket);
    ticket–;
    }
    } catch (Exception e) {
    System.out.println(“Exception==” + e);
    } finally {
    lock.unlock();
    }
    }

    public static void main(String[] args) {
    MyThread myThread = new MyThread(5);
    new Thread(myThread).start();
    new Thread(myThread).start();
    }

}

  - 实现Callable,运行完成后可返回值。

public class CallTask implements Callable {
private int upperBounds;

public CallTask(int upperBounds) {
    this.upperBounds = upperBounds;
}

@Override
public Integer call() throws Exception {
    int sum = 0;
    for (int i = 1; i <= upperBounds; i++) {
        sum += i;
    }
    return sum;
}

public static void main(String[] args) {
    ExecutorService service = Executors.newFixedThreadPool(10);
    try {
        int sum = (int) service.submit(new CallTask((int) (Math.random() * 100))).get();
        System.out.println("sum==" + sum);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}

}

- [结束线程的三种方法](https://blog.csdn.net/xu__cg/article/details/52831127)
  - run()方法执行完正常退出
  - 调用interrupt()方法
  - 使用stop方法强行终止线程(不推荐使用,Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的!)
###常用锁处理
  - [synchronized](https://www.jianshu.com/p/d53bf830fa09)  :
    - 对象锁:非静态synchronized方法,同个对象相互排斥,不同类对象不互斥
    - 类锁:静态synchronized方法和synchronized代码块方法, 不同类对象互斥,同个对象也互斥。

public class LockThread implements Runnable {
private Integer key = 0;
@Override
public void run() {
synchronized (this) {
key++;
System.out.println(Thread.currentThread().getName() + “:” + key);
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace(); }
}
}
public static void main(String[] args) {
LockThread lockThread = new LockThread();
for (int i = 0; i < 100; i++) {
new Thread(lockThread, “thread” + i).start();
}
}
}

  - lock

public class LockThread implements Runnable {
private Integer key = 0;
private Lock lock = new ReentrantLock();
@Override
public void run() {
lock.lock(); //获取锁
try {
key++;
System.out.println(Thread.currentThread().getName() + “:” + key);
Thread.sleep(5);
} catch (Exception e) {
} finally {
lock.unlock(); //释放锁
}
}
public static void main(String[] args) {
LockThread lockThread = new LockThread();
for (int i = 0; i < 100; i++) {
new Thread(lockThread, “thread” + i).start();
}
}
}

  - volatile
  ###volatile和synchronized的区别

| | volatile | synchronized  | 
| ----- | ----- | ----- | 
| 作用域 | 变量 | 方法,代码块 | 
| 操作性| 仅保证可见性,有序性| 可以保证可见性和原子性  | 
| 线程堵塞状态| 不会造成线程的阻塞| 可能会造成线程的阻塞  | 

  ###Lock和synchronized的区别
| | Lock | synchronized  | 
| ----- | ----- | ----- | 
| 使用区别 | 类 | 关键字  | 
| 作用域| 代码块| 代码块,方法 | 
| 释放锁| 需要finally()方法手动释放锁| 执行完自动释放锁  | 
| 锁类型| 可重入,可判断,可公平(两者皆可)|可重入,不可中断,非公平| 
| 依托实现| Java代码控制| JVM执行 | 
|性能|高竞争场景中表现可能优于synchronized|在低竞争场景中表现可能优于 ReentrantLock|
###sleep()和wait()的区别
| | sleep | wait  | 
| ----- | ----- | ----- | 
|| 睡眠时,保持对象锁,仍然占有该锁 | 睡眠时,释放对象锁  | 
| 作用域| 任何地方调用 | 只能在同步方法或同步块中使用| 
| 时间| 指定时间后唤醒 | 只有等notify()/notifyAll()通知有才能唤醒| 
###并发高效类
实际开发中Java封装了一些解决高并发的类包(java.util.concurrent包),常用的如下:
- AtomicInteger
提供一种线程安全的加减操作
- AtomicBoolean
- AtomicLong
- AtomicReference
- AtomicIntegerArray
- AtomicLongArray
- AtomicReferenceArray





Comments