上面我们了解了线程,接下来我们再来看看线程组
线程组:
线程组表示一个线程的集合。此外,线程组也可以包含其他线程组
下面来看个例子:
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