JAVA多线程

一、进程

1.什么是进程

  进程简单来说就是正在执行的程序。一般由程序,数据集合和进程控制块三部分组成,运行于操作系统之上。

2.进程的特征

(1)动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的
(2)并发性:任何进程都可以同其他进行一起并发执行
(3)独立性:进程是系统进行资源分配和调度的一个独立单位
(4)结构性:进程由程序,数据和进程控制块三部分组成

3.并发

  我们一边听歌,一边看文档,除此之外,电脑还运行着其他很多程序,杀毒软件、QQ、微信、eclipse等等,这些进程看上去是同时工作。但事实真相是,对于一个CPU而言,它在某个时间点只能执行一个程序,也就是说,只能运行一个进程,CPU不断地在这些进程之间轮换执行。那为什么我们感觉不到呢?
  这是因为CPU的执行速度惊人(如果启动的程序过多,我们还是能感受到速度变慢),时间片即CPU分配给各个程序的时间,每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间,使各个程序从表面上看是同时进行的。如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程,将当前进程挂起。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换,而不会造成CPU资源浪费。当又切换到之前执行的进程,把现场恢复,继续执行。所以虽然CPU在多个进程中切换执行,但我们感觉是多个程序同时在执行。

二、线程

1.什么是线程

  线程是进程内部并行的任务,是拥有资源和独立运行的最小单位,也是程序执行的最小单位。一个进程里包含多个线程。
线程

2.线程状态

(1)新建(NEW):新创建了一个线程对象。
(2)可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
(3)运行(RUNNING):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
(4)阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。
(5)死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
线程状态

3.单线程

  单线程,顺序执行,不会变异。

四、多线程并发编程

1. 并发编程三要素

(1) 原子性:指的是一个或者多个操作,要么全部执行并且在执行的过程中不被其他操作打断,要么就全部都不执行。原子性是数据一致性的保障。
(2)可见性:指多个线程操作一个共享变量时,其中一个线程对变量进行修改后,其他线程可以立即看到修改的结果。
(3)有序性:程序的执行顺序按照代码的先后顺序来执行。单线程简单的事,多线程并发就不容易保障了。

2.创建多线程的两种方式

(1)继承Thread
继承Thread

public class Test1 {
    public static void main(String[] args) {
       T1 t1 = new T1();
       T1 t2 = new T1();
       t1.start();
       t2.start();
       System.out.println("------");
    }
 
    static class T1 extends Thread {
       @Override
       public void run() {
           // 获得线程名
           String n = getName();
           // 打印1到100
           for (int i = 1; i <= 100; i++) {
              System.out.println(n + " - " + i);
           }
       }
    }
}

(2)实现Runnable
实现Runnable

public class Test2 {
    public static void main(String[] args) {
       //封装代码的对象
       R1 r1 = new R1();
       //代码交给线程
       Thread t1 = new Thread(r1);
       Thread t2 = new Thread(r1);
       //两个线程启动后,
       //都执行 r1.run()
       t1.start();
       t2.start();    
 
       //获得main线程
       Thread t = Thread.currentThread();
       String n = t.getName();
       System.out.println(n);
 
    }
 
    /*
     * 用来封装代码
     * run()方法代码要放入线程执行
     */
    static class R1 implements Runnable {
       @Override
       public void run() {
           //获得正在执行的线程对象
           Thread t = Thread.currentThread();
           String n = t.getName();
           //打印1到100
           for(int i=1;i<=100;i++) {
              System.out.println(n+" - "+i);  
           }
       }
    }
 
}

(3)比较

方式优点缺点
Thread编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。线程类已经继承了Thread类,所以不能再继承其他父类
Runnable将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值