线程
1.理解
程序:程序:保存在物理介质[光盘 软盘…]中的代码片段
进程:一旦程序运行起来 就变成了操作系统当中的一个进程 = 进行当中的程序~
线程:程序当中一条独立的执行线索
时间片:一个线程去执行的时间单位
为什么要使用多线程:根本原因 为了让程序学会同时处理多个不同的任务
2.线程的五大状态,即生命周期
新生 就绪 运行 消亡
Born Runnable Running Dead
阻塞
Blocking
3.线程的实现方法
1.extends Thread
@Override
public void run(){
//布置线程的任务
}
//启动线程调用的是start() 而不是run()!!!
2.implements Runnable //实现Runnable接口
public void run(){
//布置线程的任务
}
//不能直接start() 必须自己new一个Thread对象 把他当做参数传入
//用两种方式 实现两个线程
public class cao22{
public static void main(String[] args){
ThreadOne one = new ThreadOne();
one.start();
ThreadTwo two = new ThreadTwo();
Thread t = new Thread(two);
t.start();
}
}
class ThreadOne extends Thread{
@Override
public void run(){
for(int i=1;i<=26;i++)
System.out.println(i);
}
}
class ThreadTwo implements Runnable{
//同志们,这种方式就可以使该类不局限于单一继承的缺点
@Override
public void run(){
for(char i='a';i<='z';i++)
System.out.println(i);
}
}
4.控制线程的方法
0. setPriority(int) : 设置线程优先级别
可选范围1-10 默认优先级为5
线程优先级越高 代表抢到时间片的概率越高~
1. static sleep(long) : 让当前线程休眠指定的毫秒数~
2. static yield() : 让当前线程放弃已经持有的时间片 直接返回就绪状态
3. join() : 让当前线程邀请另一个线程优先执行
在被邀请的线程执行结束之前 主动邀请别人的当前线程不再执行 一直阻塞
一个主动邀请别人的线程: 当前处于运行状态的线程 = join写在谁的线程体当中
被邀请优先执行的线程: 主动调用方法的那个线程
*:程序当中未必只有这两个线程 弄清楚其它线程与他们的关系
*: 主动进入阻塞状态的方法 都需要进行异常处理
因为Ta们都有throws InterruptedException的声明 而这时一个非运行时异常 必须处理
*: 线程章节所有的静态方法 不要关注谁调用方法 而要关注
调用出现在谁的线程体当中 出现在哪个线程体当中 就是操作哪个线程
练习
有一个师傅线程 打印999次 "去西天西经...."
有一个猴哥线程 打印888次 "俺老孙来也~"
有一个八戒线程 打印777次 "回高老庄!!!"
有一个沙僧线程 打印666次 "大师兄不好了,师傅被妖怪抓走了~"
要求
*:请师傅的优先级设置为最低:setPriority(int);
*:猴哥前三次得到时间片都会主动放弃:yield();
*:八戒很懒 在执行操作之前要先休眠300毫秒:sleep(long);
*:废物沙僧,猴哥上之前,沙僧绝对不上。
public class BigOne{
public static void main(String[] args){
SF sf = new SF();
sf.setPriority(1);
sf.start();
WK wk = new WK();
wk.start();
WN wn = new WN();
wn.start();
WJ wj = new WJ(wk);
wj.start();
}
}
class SF extends Thread{
@Override
public void run(){
for(int i = 0;i<999;i++){
System.out.println("去西天西经....");
}
}
}
class WK extends Thread{
@Override
public void run(){
yield();
yield();
yield();
for(int i = 0;i<888;i++){
System.out.println("俺老孙来也~");
}
}
}
class WN extends Thread{
@Override
public void run(){
try{
sleep(300);
}catch(Exception e){
e.printStackTrace();
}
for(int i = 0;i<777;i++){
System.out.println("回高老庄!!!");
}
}
}
class WJ extends Thread{
WK hg;
public WJ(WK hg){
this.hg = hg;
}
@Override
public void run(){
try{
hg.join();
}catch(Exception e){
e.printStackTrace();
}
for(int i = 0;i<666;i++){
System.out.println("大师兄不好了,妖怪呗师傅抓走了~");
}
}
}
5.线程其他的常用方法
1.setName() : 设置线程的名字
2.getName() : 得到线程的名字
3.static activeCount():得到程序当中所有活跃线程的总数
活跃线程 = 就绪 + 运行 + 阻塞
注意 : 得到的结果一定是加上主线程的结果,即在数量上为原有结果+1
4.setDaemon() : 设置线程成为守护线程
守护线程是为其它线程提供服务的
当程序当中只有守护线程的时候,守护线程会自行结束
5.interrupt() : 中断/打断线程的阻塞状态
一般要配合sleep() join()使用
6.static currentThread() : 得到正在运行状态的那个线程对象
1.在main方法中,得到主线程的线程对象
2.在run()调用的其他方法中,得到当前线程是谁(可以理解为王者荣耀的大龙,此 时此刻哪个线程在打他)
3.此方法不应该出现在run()中,返回的线程就相当于this
王者荣耀,主宰(也就是大龙),需要计算此时此刻 谁在打他,打了几次
import java.util.*;
import java.util.concurrent.*;//ConcurrentHashMap & CountDownLatch~
public class TestCurrent{
public static void main(String[] args) throws Exception{
Player p1 = new Player("李白");
Player p2 = new Player("韩信");
Player p3 = new Player("露娜");
p1.start();
p2.start();
p3.start();
p1.join();
p2.join();
p3.join();
System.out.println("大龙挨打的过程如下:");
Dragon dragon = Dragon.getOnly();//得到老师对象 才能去访问那个map
Set<String> ks = dragon.map.keySet();
for(String k : ks){
System.out.println(k + " : " + dragon.map.get(k));
}
}
}
class Dragon{//大龙线程
//多线程高并发的场景下 选择ConcurrentHashMap最合适
Map<String,Integer> map = new ConcurrentHashMap<>();//大龙可以知道 是哪个玩家打的他 以及名字和次数之间的关系
private Dragon(){}
private static Dragon only = new Dragon();
public static Dragon getOnly(){
return only;
}
public void count(){//计算玩家与次数~
Thread dqxc = Thread.currentThread();//得到当前线程对象
String name = dqxc.getName();
System.out.println("是"+name+"在打我!!!!!!!!~");
//计算
Integer v = 1;
if(map.containsKey(name))
v = map.get(name) + 1;
map.put(name,v);
}
}
class Player extends Thread{ //玩家线程
public Player(String name){
setName(name);// 继承父类Thread 得到 setName()方法
}
public void run(){
System.out.println("我是" + getName() + ", 我要去打大龙~~~");
Dragon dragon = Dragon.getOnly();
int x = (int)(Math.random()*3)+2;//2-4
for(int i = 0;i<x;i++){
dragon.count();
}
}
}