1.通过继承Thread来创建线程
- 由于java单继承的机制,所以这种创建线程的方式不太推荐,当某一个类有一个直接父类,那么他就不能当线程类来使用了.
- 调用start方法相当于是创建分支栈,这个栈的run方法跟主线程的main方法是平级的,开好栈以后,由jvm自动调用.
public class Thread2 {
public static void main(String[] args) {
new Test2().start();
for (int i = 0; i < 1000; i++) {
System.out.println("主线程------->"+i);
}
}
}
class Test2 extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("分支线程------>");
}
}
}
2.通过(三种写法)来实现runnable接口来创建线程
第一种方式(创建一个实现Runnable接口的类,在把该类的实现类对象作为Thread的构造器参数来创建线程,写法比较繁琐):
public class Thread1 {
public static void main(String[] args) {
new Thread(new Test()).start();
for (int i = 0; i < 1000; i++) {
System.out.println("主线程------>"+i);
}
}
}
class Test implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("分支线程----->"+i);
}
}
}
第二种方式(通过匿名内部类的方式来创建Runnable的实现类对象,写法得到简洁):
public class Thread1 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("子线程------>"+i);
}
}
}).start();
for (int i = 0; i < 1000; i++) {
System.out.println("主线程------>"+i);
}
}
}
第三种方式(通过lambda表达式进一步简化第二种方式):
public class Thread1 {
public static void main(String[] args) {
new Thread(() -> {
for (int i = 0; i < 1000; i++) {
System.out.println("分支线程----->"+i);
}
}).start();
for (int i = 0; i < 1000; i++) {
System.out.println("主线程------>"+i);
}
}
}
3.通过实现callable接口的方式来创建线程
优点:
- 这中创建线程的方式相比上面两种方法可以获取线程的返回值
- 这种线程还可以抛出异常!
- 优点就是当要实现多个线程操作同一个资源对象的时候比较好实现
- 还可以指定返回值的泛型
缺点:
- 这种方式创建线程当要获取返回值的时候,会造成main(其他)线程阻塞的情况,
public class CallableTest {
public static void main(String[] args) {
FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("分支线程开始了---->");
int a = 100;
int b = 200;
Thread.sleep(1000*5);
return a+b;
}
});
Thread t = new Thread(futureTask);
t.start();
try {
Integer integer = futureTask.get();
System.out.println(integer);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("主线程执行了---->");
}
}
4.通过线程池的方式创建线程
线程池的相关参数:
1、corePoolSize: 核心线程数量,线程池中会存在这么多个线程,当线程数量(包含空闲线程)少于corePoolSize的时候,会优先创建新线程,可以设置allowCoreThreadTimeOut=true来让核心线程池中线程也移除
2、maximumPoolSize: 线程池的最大容量,线程池中的线程数量不得超过这么多个,除非阻塞队列设置为无界的
3、keepAliveTime: 空闲线程存活时间,线程空闲超过这个时间的时候就会销毁
4、unit: keepAliveTime的时间单位,分钟、秒等
5、workQueue: 线程工作队列,阻塞队列,线程池从这个队列中取线程,可以设置的队列类型(容量为:capacity):
ArrayBlockingQueue:有界阻塞队列,当线程数量n:corePoolSize <= n < maximumPoolSize 且 n >=
capacity :创建新线程处理任务 当:n >= maximumPoolSize 且 n >= capacity 拒绝线程
LinkedBlockingQueue: 无界队列,maximumPoolSize不起作用,会一直创建线程 会造成OOM
(outofmemory)
SynchronousQuene: 不缓存任务,直接调度执行,线程数超过 maximumPoolSize 则直接拒绝线程
PriorityBlockingQueue: 带优先级的线程队列
6、setRejectedExecutionHandler: 拒绝策略,线程数量达到maximumPoolSize时的策略,默认提供了4种:
AbortPolicy: 直接丢弃并抛出异常
CallerRunsPolicy: 线程池没有关闭则直接调用线程的run方法
DiscardPolicy: 直接丢弃任务
DiscardOldestPolicy: 丢弃最早的任务,并尝试把当前任务加入队列
7、ThreadFactory: 创建线程时使用的工厂,可以对线程进行统一设置,如是否守护线程、线程名等
通过线程池创建线程:
public class ThreadPool {
public static void main(String[] args) {
//创建带有10个线程的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
//上面的ExecutorService是一个接口,ThreadPoolExecutor是实现类对象
ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) service;
//设置核心线程的数量
poolExecutor.setCorePoolSize(5);
//设置空闲线程的存活时间
poolExecutor.setKeepAliveTime(1000*60*60,TimeUnit.SECONDS);
//设置线程最大数量
poolExecutor.setMaximumPoolSize(10);
//设置拒绝策略
poolExecutor.setRejectedExecutionHandler(new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
}
});
//设置线程工厂
poolExecutor.setThreadFactory(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
}
});
//execute主要适用于runnable方式创建的线程
service.execute(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 101; i++) {
if (i % 2 == 0){
System.out.println(i);
}
}
}
});
//submit方法既可以适用于Runnable,也适用于Callable
service.submit(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 101; i++) {
if (i % 2 == 0){
System.out.println(i);
}
}
}
});
//通过callable来实现
Future<Integer> future = service.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i < 101; i++) {
sum += i;
}
return sum;
}
});
try {
//得到线程的返回值
Integer sum = future.get();
System.out.println("1-100的偶数和为:"+sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//关闭线程池
service.shutdown();
}
}