进程与线程

进程

进程就是正在运行的程序,它会占用对应的内存区域,由CPU进行执行与计算 

 特点

独立性
   进程是系统中独立存在的实体,它可以拥有自己独立的资源,每个进程都拥有自己私有的地址空间,在没有经过进程本身允许的情况下,一个用户进程不可以直接访问其他进程的地址空间
动态性
    进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合,程序加入了时间的概念以后,称为进程,具有自己的生命周期和各种不同的状态,这些概念都是程序所不具备的.
并发性
   多个进程可以在单个处理器CPU上并发执行,多个进程之间不会互相影响.

线程 

线程是操作系统OS能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.
一个进程可以开启多个线程,其中有一个主线程来调用本进程中的其他线程。
多线程可以让同一个进程同时并发处理多个任务,相当于扩展了进程的功能 。

一个操作系统中可以有多个进程,一个进程中可以包含一个或多个线程。

多线程特点 

随机性  一个CPU【单核】只能执行一个进程中的一个线程

CPU分时调度  

  1. FCFS(First Come First Service 先来先服务算法)
  2. SJS(Short Job Service短服务算法)

线程状态

就绪(可运行)状态:线程已经准备好运行,只要获得CPU,就可立即执行
执行(运行)状态:线程已经获得CPU,其程序正在运行的状态
阻塞状态:正在运行的线程由于某些事件(I/O请求等)暂时无法执行的状态,即线程执行阻塞

串行:同一时刻一个CUP只能 处理一件事

并行:同一时刻多个CUP处理多个事件

时间片:CPU分配给各个线程的一个时间端,即线程被允许执行的时间,当CPU被分配给另一个线程时,当前线程挂起,如果线程在片时间完成之前阻塞或结束,CPU当即切换

多线程实现方式 

 一,继承

  1. 自定义一个类extends Thread
  2. 重写run()方法
  3. 创建多个线程对象
  4. 线程对象调用start(),以多线程的方式启动
public class TestThread1 {
    public static void main(String[] args) {
        TicketThread t1 = new TicketThread();
        TicketThread t2 = new TicketThread();
        TicketThread t3 = new TicketThread();
        TicketThread t4 = new TicketThread();

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
class TicketThread extends  Thread{
    static int tickets = 100;
    static Object o = new Object();
    @Override
    public void  run(){
        while (true){
//            synchronized (TicketThread.class) {
            synchronized (o) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println(getName() + "=" + tickets--);
                }
                if (tickets <= 0) break;
            }
        }
    }

}

 二、实现

  1. 自定义一个类实现Runnable接口
  2. 添加接口中未实现的抽象方法run()
  3. .创建Runnable接口的实现类【也就是自定义类】对象,作为目标业务对象
  4. .创建线程对象,通过线程对象调用start(),把线程对象加入就绪队列,Thread.currentThread().getName()获取线程名称
public class TestRunnable {
    public static void main(String[] args) {
        TickectsRunnable target = new TickectsRunnable();
        Thread t1 = new Thread(target);
        Thread t2 = new Thread(target);
        Thread t3 = new Thread(target);
        Thread t4 = new Thread(target);
        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }
}
class TickectsRunnable implements  Runnable{
      int tickets = 100;
      Object o = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (o) {
//            synchronized (TickectsRunnable.class) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                    System.out.println(Thread.currentThread().getName() + "=" + tickets--);
                }
                    if (tickets <= 0) break;
                }

        }

    }
}

实现方式有点:

  1. 耦合性不强,没有继承,后续仍然可以继承
  2. 采用实现接口的方式,后续仍然可以实现其他接口
  3. 可以给所有线程对象统一业务,业务保持一致

可能出现线程安全问题情况 :多线程程序 + 有共享数据 + 多条语句操作共享数据 

同步:每次只有一个线程独占资源,排队,效率低但是安全,synchronized也被称作同步关键字

异步:是多个线程抢占资源的效果,不排队,效率高,但数据不安全

线程池 

  1.  Executors是用来创建线程池的工具类
  2. 常用方法: newFixedThreadPool(int)用于创建指定数量的线程池对象 创建出来的线程池对象ExecutorService用来存储线程的池子,负责新建,关闭、启动,execute(Runnable任务对象) 把任务丢到线程池,newCachedThreadPool() 足够多的线程,使任务不必等待,newSingleThreadExecutor() 只有一个线程的线程池
  3. Executors工具类创建一个最多具有5个线程池对象
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestRunnable {
    public static void main(String[] args) {
        TickectsRunnable target = new TickectsRunnable();
        /*Executors是用来创建线程池的工具类,它的常用方法:
        newFixedThreadPool(int)用于创建指定数量的线程池对象
        创建出来的线程池对象ExecutorService用来存储线程的池子,负责新建,关闭、启动---*/
        //使用Executors工具类创建一个最多具有5个线程池对象
       ExecutorService pool = Executors.newFixedThreadPool(5);
       for(int i = 0;i < 5;i++){
           //excute()让线程池安排线程执行业务,每次调用都会安排一个线程对象加入就绪队列
           pool.execute(target);
       }

    }
}
class TickectsRunnable implements  Runnable{
      int tickets = 100;
      Object o = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (o) {
//            synchronized (TickectsRunnable.class) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                    System.out.println(Thread.currentThread().getName() + "=" + tickets--);
                }
                    if (tickets <= 0) break;
                }

        }

    }
}

  1. 使用锁的前提:同步需要两个或者两个以上的线程,多个线程间必须使用同一个锁
  2. 如果是继承方式,锁对象要设置成静态,如果实现方式,锁对象无需设置静态
  3. 锁对象可以是新建一个对象,不限制类型,唯一即可,也可用类名.class的方式

synchronized (锁对象){
需要同步的代码(也就是可能出现问题的操作共享数据的多条语句);
}

synchronized同步关键字可以用来修饰代码块,称为同步代码块,使用的锁对象类型任意,但注意:必须唯一!

synchronized同步关键字可以用来修饰方法,称为同步方法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值