本文参考https://blog.youkuaiyun.com/HeZhiYing_/article/details/105943962
继承Thread类
就是继承Thread类,重写run方法。由于Java是单继承的,所以这种方法用的比较少,一般都是用Runnable接口
public class testxc {
@Test
public void testThread(){
new MyThread().start();
}
}
public class MyThread extends Thread{
@Override
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
实现Runnable接口
传统的方法实现
@Test
public void testRunnable(){
new Thread(new MyThread()).start();
new Thread(new MyThread(),"快别这样说").start();
}
public class MyThreadRun implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
通过匿名内部类实现
@Test
public void testRunnable1(){
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}).start();
}
通过Lamata表达式实现
@Test
public void testRunnable2(){
new Thread(()->{
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}).start();
}
实现Callable接口
@Test
public void testCallable() throws ExecutionException, InterruptedException {
// 创建执行服务
ExecutorService service = Executors.newFixedThreadPool(3);
// 提交执行
Future<Boolean> future1 = service.submit(new MyThread());
Future<Boolean> future2 = service.submit(new MyThread());
Future<Boolean> future3 = service.submit(new MyThread());
// 获取返回值
Boolean b1 = future1.get();
Boolean b2 = future2.get();
Boolean b3 = future3.get();
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
// 关闭服务
service.shutdown();
}
public class MyThread implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
return true;
}
}
线程的五大状态
创建状态
所谓的创建状态,也就是我们的new Thread();
就绪状态
所谓的就绪状态,就是我们myThread.start();
运行状态
运行状态就是我们的代码执行。
阻塞状态
当线程等待(wait)、同步(synchronized)、sleep和join的时候
死亡状态
run()结束、main()结束
线程常用方法:
setPriority(int new Priority)更改线程的优先级
sleep(long millis)让当前线程进入休眠
join()相当于插队,插入的线程执行结束后,被插队线程继续执行。
yield()线程礼让,暂停当前的线程,并把该线程状态转化为就绪状态
interrupt()中断线程(不建议用)
isAlive()判断线程是否处于存活状态
多线程买票案例
public class testxc {
@Test
public void trick(){
MyThread myThread = new MyThread();
new Thread(myThread,"窗口1").start();
new Thread(myThread,"窗口2").start();
new Thread(myThread,"窗口3").start();
new Thread(myThread,"窗口4").start();
new Thread(myThread,"窗口5").start();
}
}
public class MyThread implements Runnable {
private int ticket = 100;
private boolean flag = true;
@Override
public void run() {
while (flag) {
System.out.println(flag+":"+ticket--);
buy();
}
}
public void buy() {
if (ticket <= 0) {
flag = false;
return;
}
try {
Thread.sleep(100);// 模拟买票延迟100ms
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":"+ ticket--);
}
}
可以看出,出现了线程安全问题,原因是在对ticket变为0之前,有多个线程同时进来。
解决办法,可以通过synchronized线程同步,可以使用同步方法和同步代码块进行解决。同步方法,也就是在方法上加一个synchronized关键字。
public class Main {
public static void main(String[] args){
MyThread myThread = new MyThread();
new Thread(myThread,"窗口1").start();
new Thread(myThread,"窗口2").start();
new Thread(myThread,"窗口3").start();
}
}
class MyTicket {
int ticket;
public MyTicket(int ticket) {
this.ticket = ticket;
}
}
class MyThread implements Runnable {
MyTicket myTicket = new MyTicket(100);
private boolean flag = true;
@Override
public void run() {
while (flag) {
buy();
}
}
public void buy() {
synchronized (myTicket) {
if (myTicket.ticket <= 0) {
flag = false;
return;
}
try {
Thread.sleep(100);// 模拟买票延迟100ms
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":"+ myTicket.ticket--);
}
}
}
。。。