上面我们了解了线程,接下来我们再来看看线程组
线程组:
线程组表示一个线程的集合。此外,线程组也可以包含其他线程组
下面来看个例子:
package com.westos.Thread4; public class MyThread implements Runnable{ public void run() { for(int x=0;x<10;x++) { System.out.println(Thread.currentThread().getName()+":"+x); } } }
package com.westos.Thread4; public class ThreadDome { public static void main(String[] args) { method1(); // method2(); } //方式2: private static void method2() { //创建资源类对象 MyThread my=new MyThread(); //创建一个新的线程组对象 ThreadGroup tg=new ThreadGroup("牛鼻的线程组"); //创建Thread类对象,新的一种Thread类构造方法 //Thread(ThreadGroup group, Runnable target, String name) Thread t1=new Thread(tg,my,"刘备"); Thread t2=new Thread(tg,my,"张飞"); //输出线程组的名字 System.out.println(t1.getThreadGroup().getName()); System.out.println(t2.getThreadGroup().getName()); System.out.println(Thread.currentThread().getName()); } //方式1: private static void method1() { //创建资源类对象 MyThread mt=new MyThread(); //创建线程对象 Thread t1=new Thread(mt,"线程1"); Thread t2=new Thread(mt,"线程2"); //调用Thread类中的getThreadGroup()方法,返回的是线程组 ThreadGroup tg1 = t1.getThreadGroup(); ThreadGroup tg2 = t2.getThreadGroup(); //然后输出线程组的名字 System.out.println(tg1.getName()); System.out.println(tg2.getName()); System.out.println(Thread.currentThread().getName()); } } 运行结果: main main main ------------- 牛鼻的线程组 牛鼻的线程组 main
上面我们了解了线程组接下来我们再来看看线程池:
线程池: 可以说是线程的容器,当线程在start()方法执行后java虚拟机运行完run方法后,线程就会被当做垃圾一样等待回收掉,但是线程池中的线程被执行后,他会重新回到线程池中等待被重新利用,这是线程池的好处
类 Executors: 一种工厂类
方法:
和线程池的创建有关系
public static ExecutorService newFixedThreadPool(int nThreads)
创建一个可重用固定线程数的线程池
让我们先来看看线程池的引入
例如:
package com.westos.Executor; public class MyThread implements Runnable{ @Override public void run() { for(int x=0;x<7;x++) { System.out.println(Thread.currentThread().getName()+":"+x); } } }
package com.westos.Executor; /** * Executors类是一个有线程池有关的工厂类 */ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExecutorDome { public static void main(String[] args) { //该方法可以确定线程池内线程的数量,返回的是一个线程池 //newFixedThreadPool(int nThreads, ThreadFactory threadFactory): 创建一个可重用固定线程数的线程池 ExecutorService ThreadGroupTool = Executors.newFixedThreadPool(2); //提交Runnable接口的方法或者callable接口 ThreadGroupTool.submit(new MyThread()); ThreadGroupTool.submit(new MyThread()); //关闭线程池 //shutdown() 启动一次顺序关闭,执行以前提交的任务,但不接受新任务。 ThreadGroupTool.shutdown(); } } 运行结果: pool-1-thread-2:0 pool-1-thread-1:0 pool-1-thread-2:1 pool-1-thread-1:1 pool-1-thread-2:2 pool-1-thread-1:2 pool-1-thread-2:3 pool-1-thread-1:3 pool-1-thread-2:4 pool-1-thread-1:4 pool-1-thread-2:5 pool-1-thread-1:5 pool-1-thread-1:6 pool-1-thread-2:6
从上面的运行结果可以看出pool代表的就是线程池,后面跟的1就是线程池的数量,再后面的thread就是线程池中的线程了
我们在之前学习过了多线程的实现方式有两种分别是:继承Thread类和实现Runnable接口,接下来让我们再看看实现多线程的第三种方式:线程池中实现Callable接口,在面试的时候,当考官询问我们关于实现多线程的方式时,我们回答出前面学习的两种就可以了,第三种如果能记得,那就更好了,可以为你加分的
现在让我们看看多线程的第三种实现方式:
package com.westos.Executor2; import java.util.concurrent.Callable; public class MyCallable implements Callable{ @Override public Object call() throws Exception { for(int x=0;x<7;x++) { System.out.println(Thread.currentThread().getName()+":"+x); } return null; } }
package com.westos.Executor2; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 实现多线程的第三种方式 * 前提得自定义类去实现Callable接口 */ public class ExecutorDome { public static void main(String[] args) { //调用Executor的返回线程池的方法 ExecutorService pool = Executors.newFixedThreadPool(2); //提交 Callable接口的方法 pool.submit(new MyCallable()); pool.submit(new MyCallable()); //关闭线程池 pool.shutdown(); } } 运行结果: pool-1-thread-1:0 pool-1-thread-1:1 pool-1-thread-1:2 pool-1-thread-1:3 pool-1-thread-1:4 pool-1-thread-1:5 pool-1-thread-1:6 pool-1-thread-2:0 pool-1-thread-2:1 pool-1-thread-2:2 pool-1-thread-2:3 pool-1-thread-2:4 pool-1-thread-2:5 pool-1-thread-2:6
可以看出依旧可以运行出多线程之间的特点
当我们想要实现线程之间的和运算应该怎么做呢?
package com.westos.Executors; import java.util.concurrent.Callable; public class MyCallable implements Callable<Integer>{ //定义一个变量 private int number; //创建该类的有参构造 public MyCallable(int number) { this.number=number; } @Override public Integer call() throws Exception { int sum=0; for(int x=0;x<=number;x++) { sum+=x; } //因为这里需要返回线程之间的和的值,所以需要将null改为sum return sum; } }
package com.westos.Executors; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class ExecutorsDome { public static void main(String[] args) throws InterruptedException, ExecutionException { //调用方法返回创建线程池 //ExecutorService:可以执行异步任务 ExecutorService pool = Executors.newFixedThreadPool(2); //提交Callable方法,返回的是future接口 //Future 表示异步计算的结果 Future<Integer> f1 = pool.submit(new MyCallable(100)); Future<Integer> f2 = pool.submit(new MyCallable(200)); //get() 如有必要,等待计算完成,然后获取其结果。 Integer i1 = f1.get(); Integer i2 = f2.get(); System.out.println(i1); System.out.println(i2); //关闭线程池 pool.shutdown(); } } 运行结果: 5050 20100