3.线程状态
五大状态
- 创建状态(新生)
- 就绪状态
- 阻塞状态
- 运行状态
- 死亡状态
1.线程方法
方法 | 说明 |
---|---|
setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield() | 暂停当前正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程,别用这个方式 |
boolean isAlive() | 测试线程是否处于活动状态 |
2.停止线程
建议使用步骤
package java_se.java_jinjie.duoxiancheng.demo03;
//测试stop
//1.建议线程正常停止-->利用次数,不建议死循环
//2.建议使用标识位-->设置一个标识位
//3.不要使用stop或destroy等过时或JDK不建议使用的方法
public class TestStop implements Runnable {
//1.设置一个标识位
private boolean flag=true;
@Override
public void run() {
int i=0;
while (flag){
System.out.println("run...Thread"+i++);
}
}
//2.设置一个公开的方法停止线程,转换标识位
public void stop(){
this.flag=false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 100; i++) {
System.out.println("main"+i);
//主线程到90的时候停止子线程
if (i==90){
testStop.stop();
System.out.println("线程该停止了");
}
}
}
}
3.线程休眠
1.模拟网络延时
package java_se.java_jinjie.duoxiancheng.demo03;
//模拟网络延时:放大问题的发生性
public class TestSleep implements Runnable{
private int ticketNums=10;
@Override
public void run() {
while (true){
if (ticketNums<=0){
break;
}
try {
Thread.sleep(200);
}catch (InterruptedException e){
e.printstacktrace();
}
System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketNums--+"张票");
}
}
public static void main(String[] args) {
TestSleep text = new TestSleep();
new Thread(text,"小明").start();
new Thread(text,"老师").start();
new Thread(text,"黄牛").start();
}
}
2.倒计时
package java_se.java_jinjie.duoxiancheng.demo03;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestSleep2 {
public static void main(String[] args) {
// //倒计时
// try {
// tenDown();
// }catch (InterruptedException e){
// e.printstacktrace();
// }
//获取系统当前时间
Date date = new Date(System.currentTimeMillis());
while (true){
try {
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
date = new Date(System.currentTimeMillis());//更新当前时间
}catch (InterruptedException e){
e.printstacktrace();
}
}
}
public static void tenDown()throws InterruptedException{
int num=10;
while (true){
Thread.sleep(1000);
System.out.println(num--);
if (num<=0){
break;
}
}
}
}
4.线程礼让(放弃、谦让、避让)
礼让线程,让当前正在执行的线程暂停,但不阻塞
将线程从运行状态转为就绪状态
让cpu重新调度,礼让不一定成功,看cpu心情
package java_se.java_jinjie.duoxiancheng.demo03;
//测试礼让线程
//礼让不一定成功,看cpu心情
public class TestYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"a").start();
new Thread(myYield,"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程停止执行");
}
}
5.线程加入(线程强制执行)
- Join合并线程,待此线程执行完成后,在执行其他线程,其他线程阻塞
- 可以想象成插队
package java_se.java_jinjie.duoxiancheng.demo03;
//测试join方法:想象成插队
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("线程vip来了"+i);
}
}
public static void main(String[] args) throws InterruptedException{
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
//主线程
for (int i = 0; i < 20; i++) {
if (i==12){
thread.join();//插队
}
System.out.println("main"+i);
}
}
}
6.线程状态观测
Thread.State
线程状态。线程可以处于以下状态之一
package java_se.java_jinjie.duoxiancheng.demo03;
public class TestState {
public static void main(String[] args) throws InterruptedException{
Thread thread =new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(100);
}catch (InterruptedException e){
e.printstacktrace();
}
}
System.out.println("");
});
//观测状态
Thread.State state = thread.getState();
System.out.println(state);//new
//观测启动后
thread.start();//启动线程
state=thread.getState();
System.out.println(state);//run
while (state!=Thread.State.TERMINATED){//TERMINATED线程终止|只要线程不终止,就一直输出状态
Thread.sleep(10);
state=thread.getState();//更新线程
System.out.println(state);//输出状态
}
}
}
7.线程优先级
- java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程;线程调度器按照优先级决定该调度哪个线程来执行
- 线程的优先级用数字来表示,范围从1~10
- 使用getPriority()和setPriority()来获取或改变优先级
建议:优先级的设定建议在start()调度前
package java_se.java_jinjie.duoxiancheng.demo03;
public class TestPriority {
public static void main(String[] args) {
//主线程默认优先级
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
Thread t3 = new Thread(myPriority);
Thread t4 = new Thread(myPriority);
//先设置优先级
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(4);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);//MAX_PRIORITY=10
t4.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
}
}
8.守护线程
package java_se.java_jinjie.duoxiancheng.demo03;
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true);//默认是false表示用户线程,正常的线程都是用户线程
thread.start();//上帝守护线程
new Thread(you).start();//你 用户线程启动
}
}
//上帝
class God implements Runnable{
@Override
public void run() {
while (true){//虚拟机
System.out.println("上帝忽悠着你");//用户线程结束,虚拟机结束需要一段时间,所以会继续运行一会
}
}
}
//你
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你一生都开心的或者");
}
System.out.println("==goodbye world==");
}
}
4.线程同步
并发
多个线程操作同一资源
同一对象被多个线程操作
例:上万人抢100张票、两个银行同时取钱
线程同步
线程安全
已知JDK中线程安全的类:
三大不安全案例
三人抢票
package java_se.java_jinjie.duoxiancheng.demo04;
//不安全的买票
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket station = new BuyTicket();
new Thread(station,"苦逼的我").start();
new Thread(station,"牛逼的你们").start();
new Thread(station,"可恶的黄牛").start();
}
}
class BuyTicket implements Runnable{
//票
private int ticketNums=10;
boolean flag=true;//外部停止方式
@Override
public void run() {
//买票
while (flag){
try {
buy();
} catch (InterruptedException e) {
e.printstacktrace();
}
}
}
private void buy()throws InterruptedException{
//判断是否有票
if (ticketNums<=0){
flag=false;
return;
}
//模拟延时
Thread.sleep(100);
//买票
System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
}
}
两人一起取钱
package java_se.java_jinjie.duoxiancheng.demo04;
//不安全的取钱
//两个人去银行取钱,账户
public class UnsafeBank {
public static void main(String[] args) {
//账户
Account account = new Account(100,"结婚基金");
Drawing you = new Drawing(account,50,"你");
Drawing girlFriend = new Drawing(account,100,"你的妻子");
you.start();
girlFriend.start();
}
}
//账户
class Account{
int money;//余额
String name;//卡名
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//银行:模拟取款
class Drawing extends Thread{
Account account;//账户
int drawingMoney;//取了多少钱
int NowMoney;//现在有多少钱
public Drawing(Account account,int drawingMoney,String name){
super(name);
this.account = account;
this.drawingMoney=drawingMoney;
}
@Override
public void run() {
//判断有没有钱
if (account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
return;
}
//sleep可以放大问题的发生性
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printstacktrace();
}
//卡内余额=余额-你取的钱
account.money = account.money-drawingMoney;
//你手里的钱
NowMoney=NowMoney+drawingMoney;
System.out.println(account.name+"余额为:"+account.money);
//Thread.currentThread().getName() = this.getName() 因为继承Thread所以两个getName相等
System.out.println(this.getName()+"手里的钱为:"+NowMoney);
}
}
不安全的集合
package java_se.java_jinjie.duoxiancheng.demo04;
import java.util.ArrayList;
//不安全的集合
public class UnsafeList {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printstacktrace();
}
System.out.println(list.size());
}
}
同步方法
- 同步方法: public synchronized void method(int args) {}
- 由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们只需要针对方法提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized方法和synchronized块.
- synchronized方法控制对“对象”的访问, 每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行
- 缺陷:若将一个大的方法申明为synchronized将会影响效率
同步方法实现抢票
package java_se.java_jinjie.duoxiancheng.demo04.demo2;
//不安全的买票
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket station = new BuyTicket();
new Thread(station,"苦逼的我").start();
new Thread(station,"牛逼的你们").start();
new Thread(station,"可恶的黄牛").start();
}
}
class BuyTicket implements Runnable{
//票
private int ticketNums=10;
boolean flag=true;//外部停止方式
@Override
public void run() {
//买票
while (flag){
try {
buy();
} catch (InterruptedException e) {
e.printstacktrace();
}
}
}
//synchronized 同步方法,锁的是this
private synchronized void buy()throws InterruptedException{
//判断是否有票
if (ticketNums<=0){
flag=false;
return;
}
//模拟延时
Thread.sleep(100);
//买票
System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
}
}
同步块
同步块实现模拟取款
package java_se.java_jinjie.duoxiancheng.demo04.demo2;
//不安全的取钱
//两个人去银行取钱,账户
public class UnsafeBank {
public static void main(String[] args) {
//账户
Account account = new Account(100,"结婚基金");
Drawing you = new Drawing(account,50,"你");
Drawing girlFriend = new Drawing(account,100,"你的妻子");
you.start();
girlFriend.start();
}
}
//账户
class Account{
int money;//余额
String name;//卡名
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
//银行:模拟取款
class Drawing extends Thread{
Account account;//账户
int drawingMoney;//取了多少钱
int NowMoney;//现在有多少钱
public Drawing(Account account,int drawingMoney,String name){
super(name);
this.account = account;
this.drawingMoney=drawingMoney;
}
//synchronized 默认锁的是this.
@Override
public void run() {
//锁的对象就是变化的量,需要增删改的对象
synchronized (account){
//判断有没有钱
if (account.money-drawingMoney<0){
System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
return;
}
//sleep可以放大问题的发生性
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printstacktrace();
}
//卡内余额=余额-你取的钱
account.money = account.money-drawingMoney;
//你手里的钱
NowMoney=NowMoney+drawingMoney;
System.out.println(account.name+"余额为:"+account.money);
//Thread.currentThread().getName() = this.getName() 因为继承Thread所以两个getName相等
System.out.println(this.getName()+"手里的钱为:"+NowMoney);
}
}
}
同步块实现不安全的集合
package java_se.java_jinjie.duoxiancheng.demo04.demo2;
import java.util.ArrayList;
//不安全的集合
public class UnsafeList {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printstacktrace();
}
System.out.println(list.size());
}
}
copyOnWrite实现不安全的集合(JUC安全类型的集合)
package java_se.java_jinjie.duoxiancheng.demo04.demo2;
import java.util.concurrent.copyOnWriteArrayList;
//测试JUC安全类型的集合
public class TestJUC {
public static void main(String[] args) {
copyOnWriteArrayList<String> list =new copyOnWriteArrayList();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printstacktrace();
}
System.out.println(list.size());
}
}
原文地址:https://www.jb51.cc/wenti/3288274.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。