欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多线程(一)认识多线程

程序员文章站 2022-05-05 21:44:59
...

认识多线程

    Java中有关多线程的只是虽然只有几章节,但是真正扩展开来几本书都不用,让我们从基础开始,一步步的学习多线程相关的知识。

1.基本概念介绍

    进程:系统中分配资源的一个调度单位。
    线程:也被称为轻量级进程,是进城中的调度单位。
    并发:多个指令轮流执行。
    并行:多个执行同时执行。
    一个程序至少有一个进程,一个进程中可以有多个线程。

2.多线程的基本实现

要想实现多线程,有以下三种方式:
(1) 继承Thread类,

    操作步骤:

  1. 定义Thread的子类,重写run()方法,作为线程执行体;
  2. 创建实例;
  3. 调用start()方法。
  我们用多线程中比较常见的一个场景来举例:车站有三个窗口一起卖10张火车票。

    测试类:

package com.ljw.Thread.TestTickets;

/**
 * Created by liujiawei on 2018/7/5.
 */
public class SellTickestByThread extends Thread{

    public SellTickestByThread(String name) {
        super(name);
    }

    int tickets = 10;


    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if(tickets > 0)
            System.out.println(getName() + "卖了以后还剩下==" + tickets--);
        }
    }

    public static void main(String[] args) {
        SellTickestByThread thread = new SellTickestByThread("一窗口");
        SellTickestByThread thread1 = new SellTickestByThread("二窗口");
        SellTickestByThread thread2 = new SellTickestByThread("三窗口");
        thread.start();
        thread1.start();
        thread2.start();

    }
}

运行结果:

Java多线程(一)认识多线程

    运行上面的代码以后,我们可以看到多线程的确发挥了作用,三个窗口都开始售卖票了,但是每个窗口都卖了十张票,一共卖了三十张,这明显是不对的。这是因为继承Thread类的多线程无法共享线程类的实例变量。


(2)实现Runnable接口:

操作步骤:

  1. 实现Runnable,重写run()方法作为线程执行体;
  2. 创建Runnable类的实例,以此作为Thread的target来创建Thread实例。

我们还是用上面的例子来测试代码:

package com.ljw.Thread.TestTickets;

/**
 * Created by liujiawei on 2018/7/5.
 */
public class SellTicketsByRunnable implements Runnable{
    int tickets = 10;
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if(tickets > 0)
            System.out.println(Thread.currentThread().getName() + "卖出以后还剩" + tickets--);
        }
    }


    public static void main(String[] args) {
        SellTicketsByRunnable sellTicketsByRunnable = new SellTicketsByRunnable();

        Thread thread = new Thread(sellTicketsByRunnable,"窗口一");
        Thread thread2 = new Thread(sellTicketsByRunnable,"窗口二");
        Thread thread3 = new Thread(sellTicketsByRunnable,"窗口三");

        thread.start();
        thread2.start();
        thread3.start();
    }

}

    运行结果:

Java多线程(一)认识多线程

    我们可以看到,这次的结果好像是我们想要的情况,窗口卖票,但票的总数不会变多,可惜的是顺序好像不太多,这个我们以后在说。我们可以知道实现Runnable接口也可以实现多线程,而且还可以共享线程类的实例变量。


(3)使用Callable和Future创建线程:

    Callable接口是Runnable接口的增强版,它提供了一个call()方法作为线程执行体,但是他可以有返回值,也可以返回报错时的异常。它和Future对象配合起来使用。
1》创建Callable接口的实现类,重写call()方法作为线程实现体,且call()方法有返回值;
2》使用FutureTask对象来包装Callable对象,同时封装了call()方法的返回值;
3》使用FutureTask对象作为Thread对象的target创建Thread实例
4》使用FutureTask对象的get()方法可以获取call()方法的返回值。
下面我们看下测试代码:
package com.ljw.Thread.TestTickets;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * Created by liujiawei on 2018/7/6.
 */
public class SellTicketsByFuture implements Callable{
    int tickets = 10;

    @Override
    public Object call() throws Exception {
        for (int i = 0; i < 100; i++) {
            if(tickets > 0)
            System.out.println(Thread.currentThread().getName() + "卖出还剩" + tickets--);
        }
        return null;
    }


    public static void main(String[] args) {
        SellTicketsByFuture sellTicketsByFuture = new SellTicketsByFuture();
        FutureTask task = new FutureTask(sellTicketsByFuture);
        FutureTask task2 = new FutureTask(sellTicketsByFuture);
        Thread thread = new Thread(task,"窗口一");
        Thread thread2 = new Thread(task2,"窗口二");
        thread.start();
        thread2.start();
    }



}

输出结果:

Java多线程(一)认识多线程

    可以看到使用Callable接口一样实现多线程的功能。



3.三种多线程创建方式的对比.

 采用Runnable和Callable接口的优缺点:
优点:(1)实现接口不影响继承,还可以再继承其他类;
 (2)这两者都可以共享同一个target,可以分享同一个资源;
缺点:编程略复杂,获取线程要通过Thread.currentThread()这种方式


采用Thread继承的优缺点:
优点:(1)编程简单
         (2)获取线程对象方便,this就可以;
缺点:无法继承其他类,无法共享target的实例变量。