1.线程
是进程的一个执行路径,线程之间可自由切换,多核cpu下,多线程能并发执行,线程之间能独立一起运行。
2.创建任务和线程
public class Test {
public static void main(String[] args) {
//创建任务
MyThread task = new MyThread();
//创建线程
//启动线程的start方法时,jvm会调用Runnable的run方法
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
}
static class MyThread implements Runnable {
@Override
public void run() {
System.out.print("线程执行了!");
}
}
3.创建线程的方式
(1).自定义的线程类实现Runnable,然后重写run方法。
(2).直接继承Thread类,然后重写run方法。(不推荐)
如果实现一个Thread类,就无法实现另一个类了,因为Java中类和类之间是单继承的,开发的时候是不太方便的,而实现Runnable接口就不一样,接口是多继承的,实现接口的个数可以有很多个。
4.线程的状态
5.线程的主要方法
(1).start():由新建到就绪;
(2).yield():由运行到就绪,线程不会阻塞;
(3).sleep()/sleep(long millis):由运行到阻塞,sleep()完后到就绪,一直拥有资源;
(4).join()/join(long millis):A调用B.join(),此时A阻塞,等到B执行完后,A到就绪;
(5).wait()/wait(long millis):由运行到阻塞,进入等待队列,只能被notify()/notifyAll()唤醒到就绪状态;
(6).notify()/notifyAll():唤醒等待队列的线程到锁池队列,竞争到锁之后进入就绪状态,
6.线程池
线程池是管理并发执行任务个数的理想方法。可以用Executor接口来执行线程池中的任务。
public class ExecutorTest {
public static void main(String[] args) {
//创建任务
Runnable task = new MyThread();
//定义一个执行器
//最大线程数3,如果执行的线程数大于3,则第4个线程需要等前面的线程执行完后才能到线程池中
ExecutorService executor = Executors.newFixedThreadPool(3);
//执行任务
executor.execute(task);
executor.execute(task);
executor.execute(task);
//关闭执行器
executor.shutdown();
}
static class MyThread implements Runnable {
private static int ticket = 100;
@Override
public void run() {
while (ticket > 0) {
synchronized (this) {
try {
if (ticket > 0) {//对this加锁,也就是ticket
System.out.print(Thread.currentThread().getName() + " ");
System.out.print("卖出第" + (100 - ticket + 1));
System.out.println("张票,剩下票数:" + (ticket - 1));
ticket--;
}
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}