Java基础知识第四篇-线程

来源:互联网 发布:网络会计若干问题探讨 编辑:程序博客网 时间:2024/06/06 00:09

线程

  • 定义:所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变为一个进程。进程是处于运行过程中的程序,并且具有一定的独立性。一个进程至少有一个线程,也可以有多个线程 。

  • 什么时候使用Runnable或Thread?

    • 取决于这个类需不需要重写run之外的方法。
    • Runnable不影响本类的继承关系,以及类组成
  • 特征:

    • 独立性:进程可以拥有自己独立的资源,每一个进程都拥有自己私有的地址空间。没有经过进程本身允许的情况下,一个用户进程不能直接访问其他进程的地址空间。
    • 动态性:进程和程序的区别在于程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合。进程中加入了时间的概念。进程具有自己的生命周期和状态。
    • 并发性:多个进程可以在单个处理器上并发执行,不会互相影响。
  • 线程的创建:

    1. 通过继承Thread类来创建并启动线程的步骤:
      • 定义Thread类的子类,重写该类的run()方法(线程执行体)
      • 创建Thread子类的实例(创建子线程)
      • 调用线程对象的start()方法来启动线程。
    2. 通过实现Runnable接口来创建并启动线程的步骤:
      • 定义Runnable接口的实现类,重写该接口的run()方法
      • 创建Runnable实现类的实例
      • 调用线程对象的start()方法来启动线程
    3. 通过创建匿名内部类来创建和启动线程
  • 线程的停止
    interrupt :唤醒一个被sleep或者被wait的线程(原理是改变循环条件)

  • 线程的五种状态:
    新建 就绪 运行 阻塞 死亡

    注意:
    线程从阻塞状态只能进入就绪状态,不可直接进入运行状态
    线程进入死亡状态后不可再次调用start()方法

  • 后台线程(守护线程,精灵线程):setDaemon(boolean)设置线程为守护线程
    该方法必须在启动之前调用
    如果所有的前台线程都死亡,则后台线程会自动死亡。如垃圾回收线程。

多线程

多线程出现安全问题的前提:

  • 对于多个线程来说,必须同时操作共享资源
  • 操作资源的代码有多条语句,如果出现挂起,未完整执行语句,由于数据未完成,导致数据发生异常

解决办法:synchronized(上锁)
每一把锁都是唯一的,所以指定一个唯一的对象,虽然允许使用任何对象作为同步监视器(锁),但是锁存在的意义是阻止两个线程对同一个共享资源进行并发访问,所以通常建议使用可能被并发访问的共享资源充当锁同步监视器(锁)。

  1. 同步代码块(互斥区)(对象为监视器(锁))
synchrinized(对象){        执行代码1;        执行代码2;}

什么情况使用:只要操作了共享数据就应该使用同步代码块

  1. 同步方法(方法)
public synchronized void test{}

同步方法的锁对象就是当前类的对象(this)

  1. 同步静态方法
    public static synchronized void test{ }
    同步方法的同步监视器是this 即调用该方法的对象 。
    静态同步方法的同步监视器(锁对象)是当前类.class

wait和sleep的区别
1. wait会放弃执行资格,会释放锁。不占用cpu
2. sleep放弃执行资格,但是不会释放锁,sleep后进入了阻塞状态,占用cpu

线程池:

wait()—让线程冻结
notify()—唤醒第一个冻结线程
notifyAll()—唤醒所有冻结线程
使用前提是有锁,因为与锁有关,且锁可以是任意对象,所以将这三个方法定义在Object中。

线程间通信时产生的线程安全问题解决办法:
1. 只要是操作了共享的数据,都需要使用同步代码块,且同步代码块的锁必须统一


2. 先判断是否继续循环,使用while来控制线程被唤醒后,必须判断是否执行,notifyAll全部唤醒线程,防止进程唤醒本类线程,导致安全问题。

生产者、消费者模式

jdk1.5之前使用while notifyAll方法,之后使用lock Condition方法实现,相比较,Lock方式更加灵活,可以指定需要启动的线程。

死锁

死锁出现的必要条件:
1. 资源匮乏
2. 有多个锁,多个线程都操作了此资源
3. 锁之间有使用对方资源的情况,必须有两把锁以上,且需锁中有锁。

原创粉丝点击