码迷,mamicode.com
首页 > 编程语言 > 详细

JAVA基础学习之多线程

时间:2015-06-14 09:36:34      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:java   多线程   

进程与线程

进程:就是正在进行的程序。其实就是一个应用程序运行时的内存空间。

线程:线程就是进程当中的一个控制单元或执行路径。进程负责空间的标示,而线程负责执行应用程序的执行顺序。

当一个进程中出现多个线程是就是多线程。每个线程在栈中都有自己的执行空间、方法区、变量。

java VM启动的时候会有一个进程java.exe。该进程中至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中。该线程称之为主线程。

线程的创建方法

创建线程中第一种方式:继承Thread类

步骤:

    1.定义类继承Thread类

    2.复写Thread类中run方法

        目的:将自定义代码存储在run方法,让线程运行。

    3.调用线程start方法

        该方法有两个作用:启动线程,调用run方法。

为什么覆盖run方法?

Thread类用于描述线程。该类定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。

也就是说Thread类中run方法,用于存储线程要运行的代码。

    线程都有自己的名称:Thread-编号 该编号从0开始,。

    static Thread currentThread();获取当前线程对象。

    getName()获取线程名称。

    设置线程名称: setName()或者构造函数。

代码实例:

class Demo extends Thread

{

    public void run()

    {

       for(int x=0; x<60; x++)

           System.out.println("demo run----"+x);

    }

}

class ThreadDemo

{

    public static void main(String[] args)

    {

       Demo d = new Demo();//创建好一个线程。

       d.start();//开启线程并执行该线程的run方法。

       //d.run();//仅仅是对象调用方法。而线程创建了,并没有运行。

       for(int x=0; x<60; x++)

           System.out.println("Hello World!--"+x);  

    }

}

第二种方式:实现Runable接口

步骤:

    1.定义类实现Runable接口

    2.覆盖Runable接口中的run方法。

        将线程运行的代码存储在run方法中。

    3.通过Thread类建立线程对象。

    4.将Runable接口的子类对象作为实际参数传递给Thread类的构造函数。Thread(Runable r)

    自定义的run方法所属的对象是Runable接口的子类对象。所以要让线程去运行指定对象的run方法。就必须明确该run方法所属的对象。

    5.调用Thread类的start方法开启线程(调用Runable接口子类中的run方法。)

售票实例:

class Ticket implements Runnable//extends Thread

{

    private  int tick = 100;

    public void run()

    {

       while(true)

       {

           if(tick>0)

           {

              System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);

           }

       }

    }

}

class  TicketDemo

{

    public static void main(String[] args)

    {

       Ticket t = new Ticket();

       Thread t1 = new Thread(t);//创建了一个线程;

       Thread t2 = new Thread(t);//创建了一个线程;

       Thread t3 = new Thread(t);//创建了一个线程;

       Thread t4 = new Thread(t);//创建了一个线程;

       t1.start();

       t2.start();

       t3.start();

       t4.start();

           }

}

两种方式的区别:

继承Thread:线程代码存放Thread子类的run方法中。

实现Runable:线程代码存放在接口的子类的run方法。

实现方式避免了单继承的局限性,在定义线程时,建议使用实现方式

线程状态

    1.被创建:等待启动,调用start启动。

    2.运行状态:具有执行资格和执行权。

    3.临时状态(阻塞):有执行资格,但是没有执行权。

    4.冻结状态:遇到sleep(time)方法和wait()方法时,失去执行资格和执行权,sleep方法时间到或者调用notify()方法时,获得执行资格,变为临时状态。

    5. 消忙状态:stop()方法,或者run方法结束。

多线程安全问题:一个线程在运行多条语句、操作同一个数据的时候,其他线程参与进来。导致错误数据的产生。

解决办法:只要让共享数据在某一时间只由一个线程执行,在此过程中其他的不能执行。所以会用到同步Sychronized(对象){需要被同步的代码}。

   对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁

同步函数:用synchronized修饰函数即可。

    锁是this。若同步函数被static修饰,所属类.class。

同步的前提

    必须有两个或两个以上线程才需要同步

    多个线程必须用同一个锁。

同步的好处是解决的线程安全问题,弊端是需要不断的判断锁,消耗资源。

多线程间通信和一些线程操作方法

线程间通信其实就是多个线程在操作同一个资源,但是操作的动作不同 

需要使用的方法有:

wait();

notify();

notifyAll(); 

上面的方法都使用在同步中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中,因为只有同步才具有锁 

为什么这些操作线程的方法要定义在Object类中呢?

因为这些方法在操作同步中线程时,都必须要标识它们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒,也就是说,等待和唤醒必须是同一个锁,而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。

同步中的死锁问题

何时会出现死锁?当同步中嵌套同步时会出现死锁。 这时会出现一个线程持有a锁要想执行下去要获取b锁,而另一个线程持有b锁要想执行下去要获取a锁。这就成了两个线程各自持有一个锁,又要获取对方的锁,这时就出现了死锁。程序会定在那执行不下去。

停止线程

只有一种,run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。

特殊情况:

当线程处于了冻结状态。就不会读取到标记。那么线程就不会结束。当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。Thread类提供该方法 interrupt();

JAVA基础学习之多线程

标签:java   多线程   

原文地址:http://blog.csdn.net/sunlei1980/article/details/46484217

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!