学习高并发编程1

学习高并发编程1

实现多线程的两个基础方式(继承Thread,实现Runable接口)

多线程的理解

  对计算机来说,每一个任务就是一个进程(Process),每一个进程里至少要有一个线程(Thread),线程是程序执行的一个路径,每一个线程都有自己的局部变量表,程序计数器,以及各自的生命周期。
  在我个人看来,可以用银行的例子来理解多线程。这里把银行比作一个操作系统,里面的用户存取款业务是一个进程,传统的单线程模式就好比银行只开了一个窗口来办理存取款,而来办理业务的用户只能排队等候,等前面的人办理完成了,才能轮到自己办理,如果一天有500个用户来办理,情况就很糟糕了。
  而多线程就像银行开设了多个窗口,每个窗口都可以办理业务,大大节省了用户办理业务的时间,甚至用户可以在1号窗口办理一会儿,再到2号窗口办理,大大提高了业务办理的总体效率。
  如果假设银行没有账务系统,个人银行金额也不会当下就同步,就有可能造成这个人取了两次钱却扣了一次的钱,这也就是之后要说的线程安全问题。

多线程的生命周期
	线程的生命周期大约有5个阶段
	1. NEW
	2. RUNABLE
	3. RUNNING
	4. BLOCKED
	5. TERMINATED

在这里插入图片描述

  1. NEW状态
      简单理解就是new Thread(),新建了一个Thread对象,此时该线程处于new状态。
  2. RUNABLE状态
      在创建了Thread对象后调用start方法,该线程进入runable状态,但是此时的线程并不会立即执行线程内逻辑,只不过是有了一个被执行的“资格”,需要注意这个状态下并不能进入blocked和terminated状态,因为要进入必须获得CPU的调度执行。
  3. RUNNING状态
      当runable状态的线程被CPU通过某种方式选中,开始执行,此时进入running状态,并且此时仍可称为runable状态
      当调用stop()方法进入terminated状态。
      当调用sleep()方法进入blocked状态。
      当获取资源锁,进入该锁的阻塞队列。
      当调用yield()方法进入runable状态。
  4. BLOCKED状态
      当在此状态时,调用stop()方法或意外死亡将进入terminated状态。
      线程阻塞结束,将进入runable状态。
      线程完成指定时间的休眠,将进入runable状态。
      当调用wait()方法后被其他线程调用notify()/notifyall()方法唤醒,进入runable状态。
      线程获取某个资源锁,进入runable状态。
      线程在blocked状态,后调用interrupt(),进入runable状态。
  5. TERMINATED状态
      terminated状态是线程的最后状态,在该状态线程将不会进入其他状态。
多线程的其中两个基本实现方式
  1. 继承Thread类
      实现多线程,需要类继承thread,重写run()方法,通过start()方法启动线程,直接上代码:下面代码是通过四个线程来实现1-50的递增。
public class ThreadMethod extends Thread{
    //线程名称
    private final String name;
    //最大处理数
    private static final int Max = 50;

    private static int index = 1;

    public ThreadMethod(String name) {
        this.name = name;
    }

    @Override
    public void run(){
        while (index <= Max){
            System.out.println("线程"+name+"----"+"当前的号码是"+(index++));
        }
    }

    public static void main(String[] args) {
        ThreadMethod threadMethod1 = new ThreadMethod("1号");
        ThreadMethod threadMethod2 = new ThreadMethod("2号");
        ThreadMethod threadMethod3 = new ThreadMethod("3号");
        ThreadMethod threadMethod4 = new ThreadMethod("4号");
        threadMethod1.start();
        threadMethod2.start();
        threadMethod3.start();
        threadMethod4.start();

    }
}

输出结果:

线程2号----当前的号码是1
线程2号----当前的号码是2
线程2号----当前的号码是3
线程2号----当前的号码是4
线程1号----当前的号码是1
线程2号----当前的号码是5
线程2号----当前的号码是6
线程4号----当前的号码是1
线程4号----当前的号码是2
线程4号----当前的号码是3
线程4号----当前的号码是4
线程4号----当前的号码是5
线程4号----当前的号码是6
线程2号----当前的号码是7
线程1号----当前的号码是2
线程2号----当前的号码是8
线程2号----当前的号码是9
线程4号----当前的号码是7
。。。

  结果显而易见,每个线程都执行了1-50的输出,而不是共同的输出1-50,这是因为index是四个实例创建的(可以通过将index静态处理)。

  1. 实现RUNABLE接口
      多线程的另一个实现方法是实现RUNABLE接口,但其实这么说并不准确。实现多线程只有构造Thread类,而实现Thread的执行逻辑单元有两种,一个是重写Thread的run()方法,另一个是实现runable的run()方法,并将Runable实例用作Thread的参数,那么这两种方法有什么区别呢,直接看代码,还是通过四个线程来实现1-50的递增。
public class RunableMethod implements Runnable{

    private int Index = 1;

    private final static int Max = 50;

    @Override
    public void run() {
        while (Index <= Max){
            System.out.println(Thread.currentThread().getName()+"当前的号码是"+(Index++));
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        final RunableMethod runableMethod = new RunableMethod();
        Thread thread1 = new Thread(runableMethod);
        Thread thread2 = new Thread(runableMethod);
        Thread thread3 = new Thread(runableMethod);
        Thread thread4 = new Thread(runableMethod);
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
    }
}

输出结果

Thread-0当前的号码是13
Thread-2当前的号码是14
Thread-3当前的号码是15
Thread-1当前的号码是16
Thread-0当前的号码是17
Thread-2当前的号码是18
Thread-3当前的号码是19
Thread-1当前的号码是20
Thread-2当前的号码是21
Thread-0当前的号码是22
Thread-1当前的号码是23
。。。

  这下结果比之前好很多,但还会出现线程安全问题(重复输出,漏输),上面代码只构造了一个实例,四个线程只执行了一个实例,所以不会出现每个线程各执行各的。

                    以上仅为个人学以后的个人观点,如有异议欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值