大家好,我是乐字节的小乐,好看好学的Java干货又来了!上一篇我们说到了Java多线程的概念以及优缺点,本文将接着说Java多线程的创建,以及多线程的状态。
一、创建线程
1、创建 Thread 的子类
创建: 继承 Thread +重写 run
启动: 创建子类对象 对象.start()
创建 Thread 子类的一个实例并重写 run 方法,run 方法会在调用 start()方法之后被执行,示例如下:
public class MyThread extends Thread {
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(20); //模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一边学习多线程");
}
}
public static void main(String[] args) {
//创建子类对象
MyThread myThread = new MyThread();
//启动线程
myThread.start();
//也可以创建匿名子类
Thread thread = new Thread(){
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(20);//模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一边玩QQ");
}
}
};
thread.start();
for(int i=0;i<10;i++){
try {
Thread.sleep(20); //模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一边玩微信...");
}
}
}
2、实现 Runnable 接口(推荐)
面向接口编程,避免单继承局限
创建: 实现 Runnable +重写 run
启动:静态代理 Thread
a)、创建真实角色 实现类对象
b)、创建代理角色 Thread 对象+真实角色的引用
c)、代理角色.start()
此方式是新建一个实现了 java.lang.Runnable 接口的类的实例,实例中的方法可以被
线程调用。
缺点: 根据重写规则,run 方法不能对外声明异常,不能有返回值
public class MyRunnable implements Runnable {
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(20); //模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一边学习多线程");
}
}
public static void main(String[] args) {
//使用代理创建线程
Thread thread = new Thread(new MyRunnable());
//启动线程
thread.start();
//也可以创建一个实现了Runnable接口的匿名类
Runnable myRunnable = new Runnable(){
public void run(){
for(int i=0;i<10;i++){
try {
Thread.sleep(20);//模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一边玩QQ");
}
}
};
Thread t = new Thread(myRunnable);
t.start();
for(int i=0;i<10;i++){
try {
Thread.sleep(20); //模拟延时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("一边玩微信...");
}
}
}
优点: 能声明异常,能有返回值 缺点: 编写复杂麻烦
public class Call {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//创建线程
ExecutorService ser=Executors.newFixedThreadPool(2);
Race tortoise = new Race("老不死",1000);
Race rabbit = new Race("小兔子",500);
//获取值
Future result1 =ser.submit(tortoise) ;
Future result2 =ser.submit(rabbit) ;
Thread.sleep(2000); //2秒
tortoise.setFlag(false); //停止线程体循环
rabbit.setFlag(false);
int num1 =result1.get();
int num2 =result2.get();
System.out.println("乌龟跑了-->"+num1+"步");
System.out.println("小兔子跑了-->"+num2+"步");
//停止服务
ser.shutdownNow();
}
}
class Race implements Callable{
private String name ; //名称
private long time; //延时时间
private boolean flag =true;
private int step =0; //步
public Race() {
}
public Race(String name) {
super();
this.name = name;
}
public Race(String name,long time) {
super();
this.name = name;
this.time =time;
}
@Override
public Integer call() throws Exception {
while(flag){
Thread.sleep(time); //延时
step++;
}
return step;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public int getStep() {
return step;
}
public void setStep(int step) {
this.step = step;
}
}
二、线程的状态及信息
1、五种状态
1)、新生状态: new
2)、就绪状态: runnable
3)、运行状态: running
4)、阻塞状态: blocked
5)、执行完毕: dead
类似于运动员赛跑,
1)、新生状态:选出运动员
2)、就绪状态:走到起跑线,做好跑的动作,枪响后,不是马上就跑,得有反应时间。
3)、运行状态:反应完成后,开始跑
4)、阻塞状态:路边一个石头绊倒了,马上跑起来,嘟囔几句,踢踢石头, 不是马上跑,重新反应进入就 绪。
5)、终止状态:跑完了,结束了,慢慢的走几步停下来。
2、阻塞: sleep
模拟网络延时,每个对象 都有一把排他锁,不会释放锁
class Web12306 implements Runnable {
private int tickets =20; //假设20张票
private boolean flag =true;
@Override
public void run() {
while(flag){
if(tickets>=0){
try {
//模拟延时
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-->抢票"+tickets--);
}else{
flag =false;
}
}
}
public static void main(String[] args) {
//真实角色 目标
Runnable target =new Web12306();
//代理角色 Thread +真实角色的引用
Thread proxy1 =new Thread(target,"黄牛A");
Thread proxy2 =new Thread(target,"路人甲");
//代理行为
proxy1.start(); //启动线程
proxy2.start(); //线程不安全,数据有问题
}
}
3、终止
不要调用 stop destory 方法 ,太暴力,一盆冷水让其停止。
a、正常执行完毕,循环 次数已经到达
b、外部干涉
1)、线程中加入标识 -->属性
2)、线程体中 使用改标识 -->死循环
3)、对外提供改变改标识的方法 setXxx() terminate() a()...
4)、外部根据适当的时机调用该方法
4、当前线程
Thread.currentThread()
5、优先级
只代表概率,不代表绝对先后顺序
MIN_PRIORITY : 1
NORM_PRIORITY :5 默认优先级
MAX_PRIORITY :10
getPriority() setPriority()
关于多线程的创建和状态就介绍到这里,下次我们再说多线程的同步和线程通信,请关注乐字节,原创文章,转载请注明出处。