多线程实战篇(二)
多线程实战篇
一:JAVA实现多线程的方式
(|.1)继承Thread类,重写Run方法
package com.mutit.demo.anspan;
/**
* @author 藤井大叔
*/
public class MyThread extends Thread {
//1.方法一:继承Thread类,重写run方法
//1.1编写run方法
public void run(){
System.out.println("111");
}
//1.2:编写main方法,运行多线程
public static void main(String[] args) {
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start();
myThread2.start();
}
}
(|.2)实现Runable接口,重写Run方法
下面展示一些 内联代码片
。
package com.mutit.demo.anspan;
import com.mutit.demo.fuill.HelloWord;
/**
* @author 藤井大叔
*/
public class MyThread extends HelloWord implements Runnable {
//1.方法二:使用Runnable接口,实现run方法
//使用Runnable接口是因为java只能单继承,就可以实现Runnable接口
//1.1编写run方法
public void run(){
System.out.println("这里是run方法");
}
//1.2:编写main方法,运行多线程
public static void main(String[] args) {
MyThread myThread1 = new MyThread();
Thread thread = new Thread(myThread1);
thread.start();
}
}
(|.3)使用线程池,添加执行任务
package com.mutit.demo.anspan;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author 本章代码摘要
* https://blog.csdn.net/u011480603/article/details/75332435
*/
public class MyRunnable {
private static int POOL_NUM = 10; //线程池数量
/**
* 实现方法三:线程池
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for(int i = 0; i<POOL_NUM; i++)
{
RunnableThread thread = new RunnableThread();
executorService.execute(thread);
}
//关闭线程池
executorService.shutdown();
}
}
class RunnableThread implements Runnable
{
@Override
public void run()
{
System.out.println("通过线程池方式创建的线程:" + Thread.currentThread().getName() + " ");
}
}
二:多线程的状态
在大部分人当中都认为线程状态只有五种,但是返过去看看源码状态是有六种,然后今天呢,就把这线程的五种和六种都一一介绍一下
先说一下五种:
线程的五种状态
(1)创建状态
创建状态可以说是你是new一个Thread的时候就开始创建了,但是还没有启动线程中的代码
(2)就绪状态
你在使用的多线程的时候呢,调用start()方法是必要的,当你的线程对象调用start()方法后,也就意味创建了系统资源,当执行run()方法后,返回start()结果,线程也就处于就绪状态了
(3)运行状态
当线程进入CPU时间后,也就是说明这个线程的运行状态开始了
(4)阻塞状态
阻塞状态是指某种原因放弃了CPU的使用权,暂时停止运行
阻塞状态也分几种:
1.等待阻塞
2.同步阻塞
3.其他阻塞
(5)死亡状态
main方法或者Run()执行结束,也可能是某种异常导致的结束,当执行结束后说明该线程也是结束了整个生命周期,死亡的多线程是不可再生
状态图
线程的六种状态
下面我再来说一说多线程的六种状态,也就是在源码上所显示的
所谓的六种状态分别是以下几种
(1)初始化
新创建了一个线程对象,但还没有调用start()方法
(2)可运行
Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)
(3)阻塞
表示线程阻塞于锁
(4)等待
进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)
(5)超时等待
该状态不同于WAITING,它可以在指定的时间后自行返回
(6)终止
表示该线程已经执行完
状态图
测试状态转换
package com.mutit.demo.pojo;
public class ThreadStateTest {
public static Object lock = new Object();
public static void main(String[] args) {
System.out.println("================================== 线程状态测试开始 ==================================");
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
Thread thread = Thread.currentThread();
String tname = thread.getName();
System.out.println("【Thread】:" + tname + "is running ---------> state : " + thread.getState());
try {
Thread.sleep(1000); // 当前线程休眠1秒
//LockSupport.parkNanos(1000*1000*1000);
} catch (Exception e){
e.printStackTrace();
}
long start = System.currentTimeMillis();
for (int i = 0; i < 1500000000L; i++) {
; // 循环模拟执行业务
}
long end = System.currentTimeMillis();
System.out.println("【Thread】:" + tname + "循环耗时:" + (end - start) + "ms");
synchronized (lock) {
try {
lock.wait(1000); // 当前线程等待1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (lock) {
try {
lock.wait(); // 当前线程一直等待
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("【Thread】" + tname + " wait over ----------> state : " + thread.getState());
}
}
}, "t1");
System.out.println("【Main】new Thread() ------------> state : " + t1.getState());
// 启动线程再看
t1.start();
System.out.println("【Main】t1.start() --------------> state : " + t1.getState());
try {
Thread.sleep(500);
// 主线程休眠0.5秒,查看t1线程状态
System.out.println("【Main】t1 sleep(1000) ----------> state : " + t1.getState());
Thread.sleep(800);
System.out.println("【Main】t1 for -----------------> state : " + t1.getState());
Thread.sleep(1000);
System.out.println("【Main】t1 wait(1000) ----------> state : " + t1.getState());
Thread.sleep(1000);
synchronized (lock) {
System.out.println("【Main】t1 wait() --------------> state : " + t1.getState());
lock.notify();
System.out.println("【Main】lock notify() ----------> state : " + t1.getState());
Thread.sleep(1000);
System.out.println("【Main】no exit sync-block ------> state : " + t1.getState());
}
Thread.sleep(10);
System.out.println("【Main】t1 over ----------------> state : " + t1.getState());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
三:终止线程的方法
stop方法(不安全,不推荐使用)
这种方法现在是差不多用不着了,也是不推荐进行使用了,因为不安全,它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在
package com.mutit.demo.pojo;
public class StopThreadTest {
public static class SellTicket implements Runnable {
int count = 2; // 剩余票数
int selled = 0; // 已经卖出票数
@Override
public void run() {
synchronized (this){
count--;
try {
Thread.sleep(1000); // 模拟买票延迟
} catch (InterruptedException e) {
e.printStackTrace();
}
selled++;
}
}
public void print(){
System.out.println("剩余票数 = " + count + ", 卖出票数 = " + selled);
}
}
public static void main(String[] args) {
SellTicket sellTicket = new SellTicket();
Thread t1 = new Thread(sellTicket);
Thread t2 = new Thread(sellTicket);
t1.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.stop();
t2.start();
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
sellTicket.print();
}
}
interrupt方法
interrupt()方法不像stop方法强行终止一个线程。它只是把要被停止的线程设置成中断状态。而此时要被中断的线程是可以继续执行的
package com.mutit.demo.pojo;
public class StopThreadTest {
public static class SellTicket implements Runnable {
int count = 2; // 剩余票数
int selled = 0; // 已经卖出票数
@Override
public void run() {
synchronized (this){
count--;
try {
Thread.sleep(1000); // 模拟买票延迟
} catch (InterruptedException e) {
e.printStackTrace();
}
selled++;
}
}
public void print(){
System.out.println("剩余票数 = " + count + ", 卖出票数 = " + selled);
}
}
public static void main(String[] args) {
SellTicket sellTicket = new SellTicket();
Thread t1 = new Thread(sellTicket);
Thread t2 = new Thread(sellTicket);
t1.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//t1.stop();
/*
* 用interrupt方法能通过抛出InterruptedException中断阻塞状态
* 避免stop方法直接结束进程导致的数据不一致
*/
t1.interrupt();
t2.start();
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
sellTicket.print();
}
}
使用标志退出
使用标志位终止线程就是定义一个boolean型的标志位 ,在线程的run方法中根据这个标志位是为true还是为false来判断是否终止,这种情况多用于while循环中
package com.mutit.demo.pojo;
public class StopThread extends Thread {
private boolean flag = true;
@Override
public synchronized void run() {
while (flag) {
System.out.println(Thread.currentThread().getName()+"---我是子线程");
}
}
public void stopThread() {
flag = false;
System.out.println(getName()+"线程被终止掉了");
}
public static void main(String[] args) {
StopThread stopThread1 = new StopThread();
StopThread stopThread2 = new StopThread();
stopThread1.start();
stopThread2.start();
for (int i = 0; i < 50; i++) {
System.out.println("------我是主线程-----"+i);
if(i==30) {
stopThread1.stopThread();
stopThread2.stopThread();
}
}
}
}
上一篇: 原生JS的AJAX读取json全过程