线程的实现方式,四线程和八线程的区别介绍

电子常识

2641人已加入

描述

  摘要:线程是程序执行流的最小单元。四线程和八线程是线程的两种表现形式,下面来看看它们之间的区别以及线程的实现方式。

  线程介绍

  线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。

  一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

  线程适用范围

  1.服务器中的文件管理或通信控制

  2.前后台处理

  3.异步处理

  线程特点

  在多线程OS中,通常是在一个进程中包括多个线程,每个线程都是作为利用CPU的基本单位,是花费最小开销的实体。线程具有以下属性。

  1)轻型实体

  线程中的实体基本上不拥有系统资源,只是有一点必不可少的、能保证独立运行的资源。

  线程的实体包括程序、数据和TCB。线程是动态概念,它的动态特性由线程控制块TCB(Thread Control Block)描述。TCB包括以下信息:

  1)线程状态。

  (2)当线程不运行时,被保存的现场资源。

  (3)一组执行堆栈。

  (4)存放每个线程的局部变量主存区。

  (5)访问同一个进程中的主存和其它资源。

  用于指示被执行指令序列的程序计数器、保留局部变量、少数状态参数和返回地址等的一组寄存器和堆栈。

  2)独立调度和分派的基本单位。

  在多线程OS中,线程是能独立运行的基本单位,因而也是独立调度和分派的基本单位。由于线程很“轻”,故线程的切换非常迅速且开销小(在同一进程中的)。

  3)可并发执行。

  在一个进程中的多个线程之间,可以并发执行,甚至允许在一个进程中所有线程都能并发执行;同样,不同进程中的线程也能并发执行,充分利用和发挥了处理机与外围设备并行工作的能力。

  4)共享进程资源。

  在同一进程中的各个线程,都可以共享该进程所拥有的资源,这首先表现在:所有线程都具有相同的地址空间(进程的地址空间),这意味着,线程可以访问该地址空间的每一个虚地址;此外,还可以访问进程所拥有的已打开文件、定时器、信号量机构等。由于同一个进程内的线程共享内存和文件,所以线程之间互相通信不必调用内核。

  线程的实现方式

  Java中有两种实现多线程的方式。一是直接继承Thread类,二是实现Runnable接口。那么这两种实现多线程的方式在应用上有什么区别呢?

  第一种方式:使用Runnable接口创建线程

  1.可以将CPU,代码和数据分开,形成清晰的模型

  2.线程体run()方法所在的类可以从其它类中继承一些有用的属性和方法

  3.有利于保持程序的设计风格一致

  第二种方式:直接继承Thread类创建对象

  1.Thread子类无法再从其它类继承(java语言单继承)。

  2.编写简单,run()方法的当前对象就是线程对象,可直接操作。

  在实际应用中,几乎都采取第一种方式

  我们用代码来模拟铁路售票系统,实现通过四个售票点发售某日某次列车的100张车票,一个售票点用一个线程表示。

  我们首先这样编写这个程序:

  Java代码 class ThreadTest extends Thread{

  private int ticket = 100;

  public void run(){

  while(true){

  if(ticket 》 0){

  System.out.println(Thread.currentThread().getName() +

  “is saling ticket” + ticket--);

  }else{

  break;

  }

  }

  }

  }

  main测试类:

  Java代码 public class ThreadDome1{

  public static void main(String[] args){

  ThreadTest t = new ThreadTest();

  t.start();

  t.start();

  t.start();

  t.start();

  }

  }

  上面的代码中,我们用ThreadTest类模拟售票处的售票过程,run方法中的每一次循环都将总票数减1,模拟卖出一张车票,同时该车票号打印出来,直接剩余的票数到零为止。在ThreadDemo1类的main方法中,我们创建了一个线程对象,并重复启动四次,希望通过这种方式产生四个线程。从运行的结果来看我们发现其实只有一个线程在运行,这个结果告诉我们:一个线程对象只能启动一个线程,无论你调用多少遍start()方法,结果只有一个线程。

  我们接着修改ThreadDemo1,在main方法中创建四个Thread对象:

  Java代码 public class ThreadDemo1{

  public static void main(String[] args){

  new ThreadTest().start();

  new ThreadTest().start();

  new ThreadTest().start();

  new ThreadTest().start();

  }

  }

  Java代码 class ThreadTest extends Thread{

  private int ticket = 100;

  public void run(){

  while(true){

  if(ticket 》 0){

  System.out.println(Thread.currentThread().getName() +

  “ is saling ticket” + ticket--);

  }else{

  break;

  }

  }

  }

  }

  从结果上看每个票号都被打印了四次,即四个线程各自卖各自的100张票,而不去卖共同的100张票。这种情况是怎么造成的呢?我们需要的是,多个线程去处理同一个资源,一个资源只能对应一个对象,在上面的程序中,我们创建了四个ThreadTest对象,就等于创建了四个资源,每个资源都有100张票,每个线程都在独自处理各自的资源。

  经过这些实验和分析,可以总结出,要实现这个铁路售票程序,我们只能创建一个资源对象,但要创建多个线程去处理同一个资源对象,并且每个线程上所运行的是相同的程序代码。在回顾一下使用接口编写多线程的过程。

  Java代码 public class ThreadDemo1{

  public static void main(String[] args){

  ThreadTest t = new ThreadTest();

  new Thread(t).start();

  new Thread(t).start();

  new Thread(t).start();

  new Thread(t).start();

  }

  }

  Java代码 class ThreadTest implements Runnable{

  private int tickets = 100;

  public void run(){

  while(true){

  if(tickets 》 0){

  System.out.println(Thread.currentThread().getName() +

  “ is saling ticket ” + tickets--);

  }

  }

  }

  }

  上面的程序中,创建了四个线程,每个线程调用的是同一个ThreadTest对象中的run()方法,访问的是同一个对象中的变量(tickets)的实例,这个程序满足了我们的需求。在Windows上可以启动多个记事本程序一样,也就是多个进程使用同一个记事本程序代码。

  可见,实现Runnable接口相对于继承Thread类来说,有如下显著的好处:

  (1)适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码,数据有效的分离,较好地体现了面向对象的设计思想。

  (2)可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。

 

  (3)有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程操作相同的数据,与它们的代码无关。当共享访问相同的对象是,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。

  四核四线程和四核八线程的区别

  4核4线就是说CPU有4个物理核心,所以任务管理器里就显示出4张CPU图表。

  八线程,可以有2种情况, 物理4核和物理8核。

  8核8线和前面4核4线一样,4核8线 就是说,使用了超线程技术,把一个物理核心,模拟成 2个逻辑核心,所以任务管理器会显示出8张CPU表。

  超线程技术让(P4)处理器增加5%的裸晶面积,就可以换来15%~30%的效能提升。但实际上,在某些程式或未对多线程编译的程式而言,超线程反而会降低效能。除此之外,超线程技术亦要操作系统的配合,普通支持多处理器技术的系统亦未必能充分发挥该技术。例如Windows 2000,英特尔并不鼓励使用者在此系统中利用超线程。原先不支持多核心的Windows XP Home Edition却支持超线程技术。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分