java中线程的总结(1)

来源:互联网 发布:大话数据库 pdf 编辑:程序博客网 时间:2024/06/06 21:26
找了很多网络上的资料以及一些关于java的面试题,发现在java线程中进程常遇到的问题就是声明周期以及创建线程的方式,另外的还有单例模式之中双重效验锁以及生产者消费者中利用使用线程来实现的两种方法(一种是使用synchronize或者使用lock+多线程,另外一种则是使用BlockingQueue+多线程)。不过这里,只是单纯的就对线程的理解做一个总结

- 线程和进程
讲到线程,一定不能忽略线程,这里就同时对线程以及进程两个都做一些基础的介绍。
  进程:是系统进行资源分配和调度的基本单位,是操作系统结构的基础。程序是指令、数据及其组织形式的描述,进程是程序的实体。
  进程具有动态性,并发性,独立性,异步性。它由程序、数据和进程控制块三部分组成。
  线程:是程序执行流的最小单元。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。
  一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。线程是程序中一个单一的顺序控制流程,是进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。
  在单个程序中同时运行多个线程完成不同的工作,称为多线程

归纳起来可以说,操作系统可以同时执行多个任务,每个任务就是进程,而进程也可以同时执行多个任务,每个任务就是线程。

  • 线程的生命周期
    下面是从网络上下载的一张图面,介绍了线程的生命周期以及其运行状态。
    线程的关系
      线程有 5 个状态,分别是:
        新建(new)
        就绪(Runnable),
        执行(Runnning),
        阻塞(Blocked)。
          阻塞三种状况:分别为(等待[wait],同步[synchronized],以及其他阻塞[例如join,sleep时间过长])
        死亡(Dead)
    其中就绪(Runnable),执行(Runnning),阻塞(Blocked)是线程的三个基本状态。
  • 创建多线程的4种方式
      无返回值的两种
    (Thread以及Runnable)
      这里先来讲讲run(),和start()的使用
      其中run()和start()都可以启动程序,并且进程中主要实现的方法都是写在run()中,不过run()在进程运行时只不过作为一个普通的方法,而start的使用,才是作为多进程的一种使用。

      下面在来讲讲Thread和Runnable
      Thread是一个类,声明方法为:
    public class Thread implements Runnable
    是继承Runnable借口的
    而Runnable之中

@FunctionalInterfacepublic interface Runnable {    public abstract void run();}

只有run()一个接口,函数的实现全部依靠于Thread
下面使用一对常用的代码(火车票出售代码)作为例子:
首先是

class MyThread1 implements Runnable {    private int ticket = 10;    private String name;    public void run() {        for (int i = 0; i < 500; i++) {            if (this.ticket > 0) {        System.out.println(Thread.currentThread().getName() + "卖票---->" + (this.ticket--));            }        }    }}

在下面代码中你可以发现,由于Runnable中没有start()的方法,只能使用Thread进行启动,由于是由同一个进程进行启动的,线程后的答案为共享的

public class RunnableDemo {    public static void main(String[] args) {        MyThread1 mt = new MyThread1();        Thread t1 = new Thread(mt, "一号窗口");        Thread t2 = new Thread(mt, "二号窗口");        Thread t3 = new Thread(mt, "三号窗口");        t1.start();        t2.start();        t3.start();    }}

运行结果:

一号窗口卖票---->10二号窗口卖票---->9三号窗口卖票---->8二号窗口卖票---->6一号窗口卖票---->7二号窗口卖票---->4三号窗口卖票---->5二号窗口卖票---->2一号窗口卖票---->3三号窗口卖票---->1

下面是Thread的示例

class MyThread2 extends Thread {    private int ticket = 10;    private String name;    public MyThread2(){    }    public MyThread2(String name) {        this.name = name;    }    public void run() {        for (int i = 0; i < 500; i++) {            if (this.ticket > 0) {    System.out.println(Thread.currentThread().getName() + "卖票---->" + (this.ticket--));            }        }    }}

下面是使用和Runnable相同的方式来启动进程

public class ThreadDemo {    public static void main(String[] args) {        MyThread2 mt1 = new MyThread2(/*"一号窗口"*/);        Thread t1=new Thread(mt1,"一号窗口");        Thread t2=new Thread(mt1,"二号窗口");        Thread t3=new Thread(mt1,"三号窗口");        t1.start();        t2.start();        t3.start();    }}

不过,对于Thread和Runnable的使用,一般来说建议使用Runnable,因为Runnable是接口,Thread是类,接口可以使用多个,父类只能有一个。并且使用Thread来实现的进程,我们同样可以通过Runnable进行实现
  有返回值的两种
(Callable+FurtureTask以及ExecutorService+Furture+Callable)
由于这两种方式使用的较少,我暂时还不怎么了解,暂时就不说了,
下面的两段网址是网络上我找到的相关资源
http://www.cnblogs.com/felixzh/p/6036074.html
http://www.importnew.com/17572.html