Java 多线程(一)

/**
* @author StormWangxhu
* @version 创建时间:2017年11月8日 上午9:41:19
*
*/

今天来学习线程。先来了解几个概念。

1、进程

1、定义:

每一个独立运行的程序都可以称为进程,即正在运行的程序。
目前大部分计算机上安装的都是多任务操作系统,既可以同时执行多个应用程序,最常见Windows,Linux,UNIX等。

2、多进程实质:

在计算机中,所有的应用程序都是由CPU执行的。对于一个CPU而言,在某一个时间点只能执行一个程序,也就是只能执行一个进程。操作系统会为一个进程分配一段有限的CPU使用时间,CPU在这段时间中执行某一个进程,然后会在下一段时间执行另一个进程。CPU运行速度很快,可在极短时间内在不同进程之间切换,给人以错觉。

2、线程

1、定义:
一个进程中可执行多个单元,这些单元称为线程。操作系统中每一个进程中至少存在一个线程。

2、
(1)单线程程序——–代码按照调用顺序依次往下执行,不出现交替执行。
(2) 多线程程序——-多段程序代码交替执行。即一个进程在执行过程中可以产生多个单线程,这些单线程运行时相互独立,并发执行。
实质:
依旧是右CPU来调度。

2、1、线程的创建

两种方式:
(1)、继承Java.lang包下的Thread类,覆写其run()方法,在run()方法中实现运行在线程上的代码。
(2)、实现java.lang包下的Runnable接口,同样在run()方法中实现运行在线程上代码。

先来看第一种方法:

package com.stormwang.ThreadDemo;
/**
* @author StormWangxhu
* @version 创建时间:2017年11月8日 上午9:41:19
*
*/
public class CreateThreadDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MyThread myThread = new MyThread();
        myThread.run();
        while(true) {
            System.out.println("main方法正在执行。");
        }

    }

}
class MyThread {

    public void run() {
        // TODO Auto-generated method stub
        while (true) {
            System.out.println("MyThread的run()方法正在main()中执行。");
        }

    }

}

运行:

这里写图片描述

会看到一直在运行一条语句。实则是单线程导致。

修改一下,继承Thread类。

package com.stormwang.ThreadDemo;
/**
* @author StormWangxhu
* @version 创建时间:2017年11月8日 上午9:41:19
*
*/
public class CreateThreadDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MyThread myThread = new MyThread();
        myThread.start();
        for(int i=0;i<50;i++) {
            System.out.println("main方法正在运行。"+i);
            if (i==20) {
                break;
            }
        }

    }

}
class MyThread extends Thread{

    public void run() {
        for(int j=0;j<50;j++) {
            System.out.println("MyThread的run()方法正在main()中执行。"+j);
            if (j==20) {
                break;
            }
        }

    }

}

运行:
这里写图片描述

回看到,在交替运行。

再来看第二种方法:
继承Thread类有一定的局限性。因为Java支持单继承,一个类一旦继承了某个父类就无法再继承Thread类。例如学生类Student类继承了Person类,就无法再继承Thread类。

所以,Thread提供了另一个构造对象;
Thread(Runnable target);
实现Runnable接口中run()方法。

package com.stormwang.ThreadDemo;
/**
* @author StormWangxhu
* @version 创建时间:2017年11月8日 上午10:31:51
*
*/
public class RunnableDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        RunnableTest ruTest = new RunnableTest();
        Thread thread = new Thread(ruTest);
        thread.start();
        int count = 0 ;
        while (true) {
            System.out.println("main方法正在运行。"+count);
            count++;
            if (count==20) {
                break;
            }
        }

    }

}

class RunnableTest implements Runnable{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        for(int i=0;i<50;i++) {
            System.out.println("Runnable中的run()方法正在运行。"+i);
            if (i==20) {
                break;
            }
        }
    }

}

运行:

这里写图片描述

也实现了多线程。

两种实现方式的区别和对比分析

以一个窗口买票的例子演示两种方式的区别:
假设有四个窗口,买100张票。
以第一中方式:

package com.stormwang.ThreadDemo;
/**
* @author StormWangxhu
* @version 创建时间:2017年11月8日 上午11:06:38
*
*/
public class TicketWindowDemo {

    public static void main(String[] args) {
        //创建4个线程
        new TicketWindowTest().start();
        new TicketWindowTest().start();
        new TicketWindowTest().start();
        new TicketWindowTest().start();


    }

}
class TicketWindowTest extends  Thread{
    private int ticketNum = 100;
    public void run() {
        while (true) {
            if (ticketNum>0) {
                Thread thread = Thread.currentThread();//获取当前线程
                String th_name = thread.getName();
                System.out.println(th_name+" 正在发售第  "+ticketNum+" 张!");
                ticketNum--;
            }
        }
    }
}

运行:

这里写图片描述

会看到,每一个售票窗口各自买了100张票,显然与实不符合。

再看第二种方式:

package com.stormwang.ThreadDemo;
/**
* @author StormWangxhu
* @version 创建时间:2017年11月8日 上午11:19:46
*
*/
public class TicketsWindowDemo_2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TicketWindow_1 ticketWindow_1  = new TicketWindow_1();
        Thread thread = new Thread(ticketWindow_1, "窗口1");
        Thread thread2 = new Thread(ticketWindow_1, "窗口2");
        Thread thread3 = new Thread(ticketWindow_1, "窗口3");
        Thread thread4 = new Thread(ticketWindow_1, "窗口4");
        thread.start();
        thread2.start();
        thread3.start();
        thread4.start();

    }

}
class TicketWindow_1 implements Runnable{
    private int ticketNumbet = 100 ;
    @Override
    public void run() {
        while(true) {
            if (ticketNumbet>0) {
                Thread thread = Thread.currentThread();  //获取当前运行run()方法的线程
                String name = thread.getName();//得到线程的名称。
                System.out.println(name+" 正在发售 第   "+ticketNumbet-- +" 张!");


            }


        }

    }

}

运行:

这里写图片描述

可以看到,四个线程共享一个runnable资源。实现了共买100张票。

以上比较,实现Runnable接口有以下几点好处:

1、适合多个相同程序代码的线程去处理同一个资源的情况,把线程与程序代码、数据有效的分离,很好的体现了面向对象的设计思想。
2、可以避免由于Java的单继承
带来的局限性。在开发中经常碰到这样情况,就是使用一个继承了某一个父类的子类创建线程,由于一个类不能同时有两个父类,所依不能用继承Thrad类的方式,那么就只能采用Runnable接口的方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值