创建线程的方式
1、继承Thread类
class MyThread extends Threads{
@Override
public void run() {}
}
//------------------------
//调用方式
MyThread thread = new MyThread();
thread.start();
2、实现Runnable接口
class MyThread implements Runnable{
@Override
public void run() {}
}
//------------------------
//调用方式
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
分析:Runnable接口中只定义了run()抽象方法,没有start()方法的定义,所以通过实现Runnable接口创建的线程是没有start()方法的;
而Thread类实现了Runnable接口,并且定义了start()方法用于启动线程,因此需要将使用Runnable接口创建的线程包装到Thread对象中,通过使用其中的start()方法启动线程
3、匿名内部类的方式通过Runnable接口创建线程对象
Thread thread = new Thread(new Runnable(){
@Override
public void run() {}
});
thread.start();
4、通过线程池进行创建
线程池的类型:
1.可缓存的线程池 newCachedThreadPool
(线程可以重复利用,故最终创建出的线程个数和代码上预计创建的线程个数是不同的)
//创建一个可缓存的线程池
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int temp = i;
//通过线程池创建线程
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("threadName:"+Thread.currentThread().getName()+",i:"+temp);
}
});
}
//最终可以观察到输出结果中,i会出现重复的,即线程被重复利用了
2.固定长度线程池 newFixedThreadPool
(线程池中只创建n个线程,之后代码中创建的线程实际上是在对线程池中的线程进行复用)
//创建一个固定长度的线程池,方法的参数为线程池中线程的个数
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int temp = i;
//通过线程池创建线程
newFixedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("threadName:"+Thread.currentThread().getName()+",i:"+temp);
}
});
}
//最终可以观察到输出结果中,i只有三个值,因为设置了线程个数为3
3.固定长度线程池 newScheduledThreadPool
(支持定时及周期性任务执行,在上一种固定长度线程池的基础上增加了定时的功能)
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(3);
for (int i = 0; i < 10; i++) {
final int temp = i;
//通过线程池创建线程
newScheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("threadName:" + Thread.currentThread().getName() + ",i:" + temp);
}
}, 3, TimeUnit.SECONDS);//3秒之后,所有线程全部启动
}
4.单线程池 newSingleThreadExecutor
(线程池中只存在一个线程)
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int temp = i;
//通过线程池创建线程
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println("threadName:" + Thread.currentThread().getName() + ",i:" + temp);
}
});
}
//停止线程池
singleThreadExecutor.shutdown();
//最终可以观察到输出结果中,i只有1个值
线程常用API
方法 | 作用 |
---|---|
Thread.currentThread() | 表示当前线程 |
Thread.sleep(1000) | 线程进入阻塞态,时间为1000ms |
getId() | 返回线程Id |
getName() | 返回线程名称 |
start() | 启动线程,执行在run()方法中定义的操作 |
setDaemon() | 将线程设置为守护线程 |
join()方法
join()方法是用于提升调用该方法的线程的优先级;可以用于调整线程的执行顺序;
(假设现在有ABC三个线程,现在需要使得三个线程的执行顺序为C->B->A)
public class JoinThread{
public static void main(String[]args){
Thread threadA = new Thread(new Runnable() {
try {
//在执行线程A的时候,先将线程B优先级调整至线程A之前
threadB.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
@Override
public void run() {
for (int i = 0; i < 30 ; i++) {
System.out.println("线程A:"+i);
}
}
});
final Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
try {
//在执行线程B的时候,先将线程C优先级调整至线程B之前
threadC.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 30 ; i++) {
System.out.println("线程B:"+i);
}
}
});
final Thread threadC = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 30 ; i++) {
System.out.println("线程C:"+i);
}
}
});
threadA.start();
threadB.start();
threadC.start();
}
}
//最终运行结果会是:在C线程打印完之后,B线程进行打印,再由A线程进行打印