Java如何实现线程的四种方式解析

概念 进程 进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能 线程 线程是进程中的一个

概念

进程

进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能

线程

线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序

程序

程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。

主线程

jvm启动后,必然有一个执行路径(线程)从main方法开始的,一直执行到main方法结束,这个线程在java中称之为主线程。

进程调度策略

java主要用的是抢占式调度 进程调度的方式参考进程调度策略

创建线程的方法(四种)

1.匿名代码块

package com.it.threads;
public class Demo2 {
    public static void main(String[] args) {
        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i <1000 ; i++) {
      System.out.println(Thread.currentThread().getName()+"---===>"+i);
                }
            }
        }.start();
        System.out.println("-----------main over--------------");
    }
}

2.继承Thread类

package com.it.threads;

/**
 * 创建线程的步骤: 1 定义一个类继承 Thread。
 * 2 重写 run 方法。
 * 3 创建子类对象,就是创建线程对象。
 * 4 调用 start 方法,开启线程并让线程执行,
 * 同时还会告诉 jvm 去调用 run 方法。
 * @version: $
 */
public class ThreadA extends Thread {
    /**
     * 线程的任务写在run方法中
     */
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName() + "-->" + i);
        }
    }
    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        //设置线程的名字
        threadA.setName("得力");
        threadA.setPriority(10);
        //设置线程的优先级
        ThreadA threadA1 = new ThreadA();
        //设置线程的名字
        threadA1.setName("得力1");
        threadA1.setPriority(Thread.MIN_PRIORITY);
        threadA1.start();
        threadA.start();
        System.out.println(threadA.getPriority());
        System.out.println(threadA1.getPriority());
    }
}

3.实现Runnable接口

package com.it.threads;
/**
 * 1、定义类实现 Runnable 接口。
 * 2、覆盖接口中的 run 方法。。
 * 3、创建 Thread 类的对象
 * 4、将 Runnable 接口的子类对象作为参数传递给 Thread 类的构造函数。
 * 5、调用 Thread 类的 start 方法开启线程。
 * @version:     $
 */
public class ThreadB implements  Runnable {
    @Override
    public void run() {
        for (int i = 0; i <1000 ; i++) {
            System.out.println(Thread.currentThread().getName()+"---->"+i);
        }
    }
    public static void main(String[] args) {
        ThreadB threadB = new ThreadB();
        Thread thread1 = new Thread(threadB,"aa");
        Thread thread2 = new Thread(threadB,"bb1");
        //启动线程
        thread1.start();
        thread2.start();
    }
}

4.线程池

线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。 实现线程池分为两种

(1)实现Runnable

创建一个线程

package com.it.threadpool;
//方式一    实现Runnable接口
public class ThreadRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i <2; i++) {
           System.out.println(Thread.currentThread().getName()+i+"进入电影院");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+i+"离开电影院");
        }
    }
}

创建线程池

package com.it.threadpool;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
* 创建线程池对象
创建Runnable接口子类对象
提交Runnable接口子类对象
关闭线程池
* */
public class ThreadRunnablePool {
    public static void main(String[] args) {
        //创建线程池对象 线程个数  Executors:线程池创建工厂类  ExecutorService:线程池类
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        //创建Runnable实例对象
        ThreadRunnable threadRunnable = new ThreadRunnable();
        //从线程池中获取线程对象,然后调用run()
        executorService.submit(threadRunnable);
        executorService.submit(threadRunnable);
        executorService.submit(threadRunnable);
        executorService.shutdown();
    }
}

(2)实现Callable接口

创建线程

package com.it.threadpool;

import java.util.concurrent.Callable;

public class ThreadCallable implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("我要一个教练:call");
        Thread.sleep(2000);
        System.out.println("教练来了: " +Thread.currentThread().getName());
        System.out.println("教我游泳,交完后,教练回到了游泳池");
        return null;
    }
}

创建线程池

package com.it.threadpool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadCallablePool {
    public static void main(String[] args) {
        //创建线程池
        ExecutorService service = Executors.newFixedThreadPool(2);
        //生成Callable对象
        ThreadCallable threadCallable=new ThreadCallable();
        //从线程池中获取线程对象,然后调用run()
        service.submit(threadCallable);
        service.submit(threadCallable);
        service.submit(threadCallable);
        service.shutdown();
    }
}

这两种方式的区别如下:

  • Callable定义的方法是call,而Runnable定义的方法是run。
  • Callable的call方法可以有返回值,而Runnable的run方法不能有返回值,这是核心区别。
  • Callable的call方法可抛出异常,而Runnable的run方法不能抛出异常。

举一个例子说明 创建一个线程用来求和

package com.it.threadpool;
import java.util.concurrent.Callable;
public class ThreadSum implements Callable<Integer> {
    int x;
    int y;
    public ThreadSum(int x, int y) {
        this.x = x;
        this.y = y;
    }
    @Override
    public Integer call() throws Exception {
        return x+y;
    }
}

创建线程池

package com.it.threadpool;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadSumPool {
    public static void main(String[] args) {
     ExecutorService executorService= Executors.newFixedThreadPool(5);
     //Future用来接收call方法的返回值
        Future future1=executorService.submit(new ThreadSum(200,500));
        Future future2=executorService.submit(new ThreadSum(100,500));
        Future future3= executorService.submit(new ThreadSum(200,600));
        try {
        //get()方法用来获取返回值
            System.out.println(future1.get());
            System.out.println(future2.get());
            System.out.println(future3.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

到此这篇关于Java实现线程的四种方式解析的文章就介绍到这了,更多相关Java实现线程内容请搜索好代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持好代码网!

您可能有感兴趣的文章
Java 实例 - 字符串反转

Java实例--字符串替换

Java实例--删除字符串中最后一个字符

Java实例--查找字符串最后一次出现的位置

Java实例--字符串比较