版权声明: https://blog.csdn.net/qq_33278885/article/details/81590274
Java中使用ThreadGroup来表示线程组
它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。
默认情况下,所有的线程都属于主线程组。
public final ThreadGroup getThreadGroup()
我们也可以给线程设置分组
Thread(ThreadGroup group, Runnable target, String name)
public class MyRunnable implements Runnable {
public void run(){
for(int x=0;x<100;x++){
System.out.println(Thread.currentThread().getName()+"---"+x);
}
}
}
public class ThreadGroupDemo {
public static void main(String[] args) {
//method();
method2();
}
private static void method2() {
// 我们如何修改线程所在的组呢?
// 创建一个线程组
// 创建其他线程的时候,把其他线程的组指定为我们自己新建线程组
//创建线程组
ThreadGroup group=new ThreadGroup("新建的线程池");
MyRunnable m=new MyRunnable();
//现在我们需要将其他的线程指定为我们自己的线程
// Thread(ThreadGroup group, Runnable target, String name)
Thread t1=new Thread(group,m,"线程1");
Thread t2=new Thread(group,m,"线程1");
//现在我们检查一下,看这两个线程是那个线程组的
System.out.println(t1.getThreadGroup().getName()); //新建的线程池
System.out.println(t2.getThreadGroup().getName()); //新建的线程池
System.out.println(Thread.currentThread().getThreadGroup().getName()); //main
}
private static void method() {
MyRunnable m=new MyRunnable();
Thread t1=new Thread(m,"阿杰");
Thread t2=new Thread(m,"阿冬");
//现在我想知道这两个线程的线程组是那个应该怎么办?
// 线程类里面的方法:public final ThreadGroup getThreadGroup()
ThreadGroup groupone=t1.getThreadGroup();
ThreadGroup grouptwo=t2.getThreadGroup();
// 线程组里面的方法:public final String getName()
System.out.println(groupone.getName());
System.out.println(grouptwo.getName());
//得到答案是mian线程,那么主线程的线程池是那个?
// 通过结果我们知道了:线程默认情况下属于main线程组
// 通过下面的测试,你应该能够看到,默任情况下,所有的线程都属于同一个组
System.out.println(Thread.currentThread().getThreadGroup().getName());
}
}
线程池
程序启动一个新线程成本是比较高的,
因为它涉及到要与操作系统进行交互。
而使用线程池可以很好的提高性能,
尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池
Runnable对象
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
* 线程池的好处:线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
*
* 如何实现线程的代码呢?
* A:创建一个线程池对象,控制要创建几个线程对象。
* public static ExecutorService newFixedThreadPool(int nThreads)
* B:这种线程池的线程可以执行:
* 可以执行Runnable对象或者Callable对象代表的线程
* 做一个类实现Runnable接口。
* C:调用如下方法即可
* Future<?> submit(Runnable task)
* <T> Future<T> submit(Callable<T> task)
* D:我就要结束,可以吗?
* 可以。
* */
public class ExecutorsDemo {
public static void main(String[] args) {
//newFixedThreadPool此方法为静态方法直接用
//创建线程池pool 并设置其有两个线程
ExecutorService pool=Executors.newFixedThreadPool(2);
//可以执行Runnable对象或者Callable对象代表的线程
pool.submit(new MyRunnable());
pool.submit(new MyRunnable());
//结束
pool.shutdown();
}
}
public class MyRunnable implements Runnable {
@Override
public void run() {
for(int x=0;x<100;x++ ){
System.out.println(Thread.currentThread().getName()+"----"+x);
}
}
}
Callable对象
Callable好处:
可以有返回值
可以抛出异常
弊端:
代码比较复杂,所以一般不用
实现没有返回值的:
import java.util.concurrent.Callable;
public class MyCallable implements Callable {
@Override
public Object call() throws Exception {
for(int x=0;x<100;x++ ){
System.out.println(Thread.currentThread().getName()+"----"+x);
}
return null;
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*
* 线程池的好处:线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
*
* 如何实现线程的代码呢?
* A:创建一个线程池对象,控制要创建几个线程对象。
* public static ExecutorService newFixedThreadPool(int nThreads)
* B:这种线程池的线程可以执行:
* 可以执行Runnable对象或者Callable对象代表的线程
* 做一个类实现Callable接口。
* C:调用如下方法即可
* Future<?> submit(Runnable task)
* <T> Future<T> submit(Callable<T> task)
* D:我就要结束,可以吗?
* 可以。
* */
public class ExecutorsDemo {
public static void main(String[] args) {
//创建线程池
ExecutorService Pool=Executors.newFixedThreadPool(2);
//运行线程
Pool.submit(new MyCallable());
Pool.submit(new MyCallable());
//结束
Pool.shutdown();
}
}
实现有返回值的:
import java.util.concurrent.Callable;
//Callable:是带泛型的接口。
//这里指定的泛型其实是call()方法的返回值类型。
public class MyCallable implements Callable<Integer> {
private int number;
MyCallable(Integer num){this.number=num;}
@Override
public Integer call() throws Exception {
Integer num=0;
for(int x=0;x<=number;x++){
num+=x;
}
return num;
}
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/*
* 线程池的好处:线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
*
* 如何实现线程的代码呢?
* A:创建一个线程池对象,控制要创建几个线程对象。
* public static ExecutorService newFixedThreadPool(int nThreads)
* B:这种线程池的线程可以执行:
* 可以执行Runnable对象或者Callable对象代表的线程
* 做一个类实现Callable接口。
* C:调用如下方法即可
* Future<?> submit(Runnable task)
* <T> Future<T> submit(Callable<T> task)
* D:我就要结束,可以吗?
* 可以。
* */
public class ExecutorsDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//需求现在实现一个求和的多线程程式,要求是从1加到这个数本身
// 创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);
// 可以执行Runnable对象或者Callable对象代表的线程
Future<Integer> f1 = pool.submit(new MyCallable(100));
Integer a=f1.get();
System.out.println(a);
// 结束
pool.shutdown();
}
}
匿名内部类线程:
匿名内部类方式使用多线程
new Thread(){代码…}.start();
New Thread(new Runnable(){代码…}).start();
/*
* 匿名内部类的格式:
* new 类名或者接口名() {
* 重写方法;
* };
* 本质:是该类或者接口的子类对象。
*/
public class ThreadDemo {
public static void main(String[] args) {
// 继承Thread类来实现多线程
new Thread() {
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + ":"
+ x);
}
}
}.start();
// 实现Runnable接口来实现多线程
new Thread(new Runnable() {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + ":"
+ x);
}
}
}) {
}.start();
// 更有难度的
new Thread(new Runnable() {
@Override
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println("hello" + ":" + x);
}
}
}) {
public void run() {
for (int x = 0; x < 100; x++) {
System.out.println("world" + ":" + x);
}
}
}.start();
}
}