进程-线程

进程Process,处于运行中的程序,系统进行资源分配和调度的独立单位,拥有独立的内存空间(堆)。

  • 动态性:生命周期和状态;
  • 独立性:独立实体;
  • 并发性:Concurrency,抢占式多任务操作策略;

注:并发性是同一时刻只有一条指令执行,但是CPU是在多进程间快速切换;并行性,parallel,是同一时刻有多条指令在多个处理器上同时执行。

线程Thread,(轻量级进程,LightWeight Process),线程是进程的执行单元,在进程(程序)中是独立的、并发的执行流。线程是抢占式执行的,一个线程可以创建和撤销另一个线程。

线程是进程的组成部分,线程的调度和管理由进程负责。一个线程必须有一个父进程,一个进程可以拥有多个线程,多个线程共享进程的全部(系统)资源、进程代码段等,但是线程有独立的堆栈、寄存器集合、局部变量、程序计数器等,不同线程之间相互独立。线程在进程(程序)中的地位,等同于进程在操作系统中的地位。

操作系统可以执行多个任务(进程),进程可以并发处理多个任务(线程)。

多线程,隔离程度小、并发性能好。

  • 进程创建代价大;
  • 线程共享进程内存空间;

参见:线程总结


创建线程

继承java.lang.Thread类,重写run()方法

public class Thread implements Runnable {
private Runnable target;
public Thread() {}
public synchronized void start() {}
@Override
public void run() {}
private void exit() {}
public final native boolean isAlive();
}

 特点

  • 简单易实现,利用this直接获取当前线程;
  • 线程类已经继承了Thread类,不能再继承其他类;
  • 线程类的多个线程无法共享线程类的实例变量;

 步骤

  • 定义Thread类的派生类,重写Thread类的run()方法;
  • 创建Thread派生类的实例(线程对象);
  • 调用线程对象的start()方法,启动线程;
public class MyThread extends Thread
{
public void run(){
// 线程执行体
System.out.println( getName() + ":" + getId() );
}
public static void main(String[] args){
System.out.println(Thread.currentThread().getName());
MyThread myThread = new MyThread();
myThread.start();
}
}

实现java.lang.Runnable接口,实现run()方法

@FunctionalInterface
public interface Runnable {
public abstract void run();
}   

 特点

  • 实现较复杂,必须利用Thread.currentThread()方法访问当前线程;
  • 线程类只是实现了Runnable/Callable接口,还可以继承其他类,避免Java单继承的限制;
  • 线程类的多个线程可以共享同一个target对象(共享线程类[实际上应该是线程的target类]的实例变量);
  • 代码可以被多个线程共享,代码和数据独立,适合多个相同线程访问同一资源;
  • Runnable接口是函数式接口,可以利用Lambda表达式创建Runnable对象;

步骤

  • 定义Runnable接口的实现类,实现Runnable接口的run()方法;
  • 创建Runnable接口实现类的实例,并以此实例作为Thread的target来创建Thread对象;
  • 调用线程对象的start()方法,启动线程;
public class MyRunnable implements Runnable
{
public void run(){
// 线程执行体
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args){
System.out.println(Thread.currentThread().getName());
MyRunnable myRunnable = new MyRunnable();
Thread myThread = new Thread(myRunnable, "sqh-Runnable");
myThread.start();
}
} 

实现java.lang.Callable接口,结合Future和线程池

 特点

  • 同Runnable;
  • Callable接口是函数式接口,可以利用Lambda表达式创建Callable对象;

 步骤

  • 定义Callable接口的实现类,实现Callable接口的call()方法;
  • 创建Callable接口实现类的实例,并用FutureTask类封装Callable对象;
  • 利用FutureTask对象作为Thread对象的target创建线程Thread对象,并调用线程对象的start()方法,启动线程;
  • 通过FutureTask对象的get()方法获取call()方法的返回值;

其中,call()方法可以有返回值,可以声明抛出异常。

public class MyCallable implements Callable<String>
{
public String call() throws Exception {
// 线程执行体
return Thread.currentThread().getName();
}
public static void main(String[] args){
System.out.println(Thread.currentThread().getName());
MyCallable myCallable = new MyCallable();
FutureTask<String> ft = new FutureTask<String>(myCallable);
Thread myThread = new Thread(ft, "sqh-Callable").start(); try{
System.out.println(ft.get());
}
catch(Exception e){
e.printStackTrace();
}
}
}  

线程状态

  • 新生状态(New)
  • 就绪状态(Runnable)
  • 运行状态(Running)
  • 阻塞状态(Blocked)
  • 死亡状态(Dead)

每个 Java 对象都有一个(内置的)锁对象,而且只有一把钥匙。创建锁对象:

  • this 关键字
  • 类名.class
  • 对象.getClass()

注意以下几个小知识点

  • 线程进入 Sleep() 睡眠状态时,线程仍然持有锁、不会释放
  • 同步方法会影响性能(死锁),优先考虑同步代码块

死锁

当多个线程完成某个功能需要同时获取多个共享资源的时候可能会导致死锁

两个任务以相反的顺序申请两个锁:线程T1获得锁L1,线程T2获得锁L2,然后T1申请获得锁L2,同时T2申请获得锁L1。

避免死锁

线程通信

等待唤醒机制:Java 通过 Object 类的 wait,notify,notifyAll 方法实现线程间通信

  • wait:告诉当前线程放弃执行权,并放弃锁、进入阻塞状态,直到其他线程获得执行权,并持有相同的锁、调用notify为止
  • notify:唤醒持有同一个锁的调用了 wait 的第一个线程,该线程进入可运行状态、等待获取执行权
  • notifyAll:唤醒持有同一个锁的调用了 wait 的所有的线程

其中,操作线程的等待和唤醒必须是针对同一个锁对象(锁可以是任一对象,Object 类)。

注意,sleep() 和 wait() 方法的区别

  • sleep():释放资源,不释放锁,Thread的方法
  • wait(): 释放资源,释放锁,Object的方法

线程间通信,其实就是多个线程在操作同一个资源,但操作动作不同。

关于线程的 join() 方法

join 可以用来临时加入线程执行:当A线程执行到了B线程join方法时,A就会等待,直到B线程都执行完、A才会执行。

Java - 多线程与锁的更多相关文章

  1. JAVA多线程与锁机制

    JAVA多线程与锁机制 1 关于Synchronized和lock synchronized是Java的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码 ...

  2. Java 多线程:锁(一)

    Java 多线程:锁(一) 作者:Grey 原文地址: 博客园:Java 多线程:锁(一) CSDN:Java 多线程:锁(一) CAS 比较与交换的意思 举个例子,内存有个值是 3,如果用 Java ...

  3. Java 多线程:锁(二)

    Java 多线程:锁(二) 作者:Grey 原文地址: 博客园:Java 多线程:锁(二) CSDN:Java 多线程:锁(二) AtomicLong VS LongAddr VS Synchroni ...

  4. Java 多线程:锁(三)

    Java 多线程:锁(三) 作者:Grey 原文地址: 博客园:Java 多线程:锁(三) CSDN:Java 多线程:锁(三) StampedLock StampedLock其实是对读写锁的一种改进 ...

  5. java多线程----悲观锁与乐观锁

    java多线程中悲观锁与乐观锁思想 一.悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线 ...

  6. (转)java 多线程 对象锁&类锁

    转自:http://blog.csdn.net/u013142781/article/details/51697672 最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不 ...

  7. java多线程之锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁

    转载至:https://blog.csdn.net/zqz_zqz/article/details/70233767 之前做过一个测试,详情见这篇文章<多线程 +1操作的几种实现方式,及效率对比 ...

  8. Java多线程--公平锁与非公平锁

    上一篇文章介绍了AQS的基本原理,它其实就是一个并发包的基础组件,用来实现各种锁,各种同步组件的.它包含了state变量.加锁线程.等待队列等并发中的核心组件,现在我们来看一下多线程获取锁的顺序问题. ...

  9. java多线程编程——锁优化

    并发环境下进行编程时,需要使用锁机制来同步多线程间的操作,保证共享资源的互斥访问.加锁会带来性能上的损坏,似乎是众所周知的事情.然而,加锁本身不会带来多少的性能消耗,性能主要是在线程的获取锁的过程.如 ...

  10. Java多线程之锁优化策略

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6561264.html  锁的优化策略 编码过程中可采取的锁优化的思路有以下几种: 1:减少锁持有时间 例如:对 ...

随机推荐

  1. Mesos的资源分配

    Apache Mesos能够成为最优秀的数据中心资源管理器的一个重要功能是面对各种类型的应用,它具备像交警一样的疏导能力.本文将深入Mesos的资源分配内部, 探讨Mesos是如何根据客户应用需求,平 ...

  2. python中函数作用域

    在python中,一个函数就是一个作用域 name = 'xiaoyafei' def change_name(): name = 'sthu' print('在change_name里的name:' ...

  3. 我为什么使用Kubuntu

    网上看贴,包括身边的同事.朋友,总会问的问题是:我该选择哪个Linux发行版?使用久了,就会觉得这个问题其实不是问题,纯属个人习惯而已,当你真正习惯.理解了Linux,那么任何一个发行版的优点,你都有 ...

  4. cocos2dx 屏幕分辨率问题

    做手机上的软件首先要考虑的就是屏幕分辨率怎么解决.coco2dx已经有了很好的解决方法. 用cocos2dx的python脚本创建工程时默认生成一个Helloworld的demo.我们就以这个demo ...

  5. OpenCV学习记录(一):使用haar分类器进行人脸识别 标签: opencv脸部识别c++ 2017-07-03 15:59 26人阅读

    OpenCV支持的目标检测的方法是利用样本的Haar特征进行的分类器训练,得到的级联boosted分类器(Cascade Classification).OpenCV2之后的C++接口除了Haar特征 ...

  6. Centos7下安装与卸载Jdk1.8

    安装 去官网下载jdk:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 使用xs ...

  7. 大佬福利之在你眼中 Web 3.0 是什么?(转)

    web 3.0 Web 3.0一词包含多层含义,用来概括互联网发展过程中某一阶段可能出现的各种不同的方向和特征.Web 3.0 充满了争议和分歧,它到底应该什么样?具体的标志点又是什么? Web 2. ...

  8. zrender源码分析--初探如何画一个圆

    今天是想看看使用zrender框架如何去,画一个圆,再加“circle”的文字在圆心. 然后开始代码: 如何部署代码,让zrender跑起来这边就不说了,官方例子就有写,地址是:https://git ...

  9. ACM 超级楼梯 发工资

    超级楼梯 有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法? Input 输入数据首先包含一个整数N,表示测试实例的个数,然后是N行数据,每行包含一个整数M( ...

  10. [Delphi]接口认识

    Delphi中的接口用 interface 进行声明.接口是针对行为方法的描述,而不管他实现这种行为方法的是对象还是别的什么东西.因此,接口和类的出发点是不一样的,是在不同的角度看问题. 接口通过GU ...