Java多线程(中)
线程状态
方法
- setPriority(int new Priority)更改线程的优先级
- static void sleep(long millis)在指定的毫秒数内让当前正在执行的线程休眠
- void join()等待该线程终止
- static void yield()暂停当前正在执行的线程对象,并执行其他线程
- void interrupt()中断线程,不建议用这个方式
- boolean isAlive()测试线程是否处于活动状态
停止线程
/*
测试stop
1.建议线程正常终止-->利用次数,不建议死循环
2.建议使用标志位
3.不要使用stop或destroy等过时或者JDK不建议使用的方法
*/
public class TestStop implements Runnable{
//1.设置一个标志位
private boolean flag = true;
public void run(){
int i = 0;
while(flag){
System.out.println("run... Thread"+i++);
}
}
//2.设置一个公开的方法停止线程,转换标志位
public void stop(){
this.flag = false;
}
piblic static void main(String[] args){
TestStop testStop = new TestStop();
new Thread(testStop).start();
for(int i = 0; i<1000; i++){
System.out.println("main"+i);
if(i = 900){
//调用stop方法转换标志位,让线程停止
testStop.stop();
System.out.println("Thread is stop");
}
}
}
}
线程休眠
⚠️每个对象都有一个锁,sleep不会释放锁
/*
模拟网络延时:放大问题的发生性
*/
//模拟倒计时
public class TestSleep{
public static void main(String[] args){
try{
tenDown();
}catch(InterruptedException e){
e.printStackTrace();
}
}
public void tenDown() throws InterrupedException{
int num = 10;
while(true){
Thread.sleep(1000);
System.out.println(num--);
if(num <=0){
break;
}
}
}
}
线程礼让yield
让当前正在执行的线程暂停,但不阻塞
从运行转为就绪
让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{
public void run(){
System.out.println("START");
Thread.yield();//礼让
System.out.println("END");
}
}
线程强制执行join
插队
public class TestJoin implements Runnable{
publlic void run(){
for(int i=0; i<100; i++){
System.out.println("VIP is coming " + i);
}
}
public static void main(String[] args){
//启动线程
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();
//主线程
for(int i=0; i<1000; i++){
if(i == 200){
thread.join();//插队
}
System.out.println("main "+i);
}
}
}
观测线程状态
//观察测试线程的状态
public class TsetState{
public static void main(String[] args) throws InterruptedExecption{
Thread thread = new Thread(()->{
for(int i=0; i<5; i++){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println("-------");
});
//观察状态
Thread.State state = thread.state();
System.out.println(state);//NEW
//观察启动后
thread.start();
state = thread.state();
System.out.println(state);//RUN
while(state != Thread.State.TERMINATE){//只要线程不停止,就一直输出
Thread.sleep(100);
state = thread.state();
System.out.println(state);
}
}
}
线程的优先级
priority优先级,从1到10
优先级高了也不一定先执行,看CPU怎么调取,但是优先级高了权重就大,获得调度的概率更高
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);
Thread t5 = new Thread(myPriority);
Thread t6 = new Thread(myPriority);
//先设置优先级,再启动
t1.start();
t2.serPriority(1);
t2.start();
t3.serPriority(4);
t3.start();
t4.serPriority(Thread.MAX_PRIORITY);//10
t4.start();
t5.serPriority(-1);//报错
t5.start();
t6.serPriority(11);//报错
t6.start();
}
}
class MyPriority implements Runnable{
public void run(){
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
}
}
守护线程daemon
线程分为用户线程和守护线程 eg:用户线程main()
虚拟机必须确保用户线程执行完毕
虚拟机不用等待守护线程执行完毕 eg:后台记录操作日志、监控内存、垃圾回收等待
thread.setDaemon(true);默认为false,即用户线程,正常的线程都是用户线程
线程同步机制
多个线程操作同一个资源
并发:同一个对象被多个线程同时操作
线程同步其实就是一种等待机制,多个需要同时访问此对象的线程进入这个对象的等待池形成队列,等待前面线程使用完毕,下一个线程再使用
形成条件:队列+锁
为了保证数据在方法中被访问时的正确性,在访问时加入锁机制synchronized,当一个线程获得对象的排它锁,独占资源,其他线程必须等待,使用后释放锁即可
存在问题:提高安全,但是损失性能
每个线程都在自己的工作内存进行数据交互,如果操作不当容易造成数据的错误
⚠️线程不安全的集合:ArrayList 把数据放到同一个位置,就替换掉了
同步方法
synchronized方法和synchronized块
每个对象一把锁,每个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程会阻塞,方法一旦执行就独占该锁
//同步方法
public class TestTicket{
public static void main(String[] args){
BuyTicket buyer = new BuyTicket();
new Thread(nuyer,"jack").start();
new Thread(buyer,"tomy").start();
new Thread(buyer,"namy").start();
}
}
class BuyTicket implements Runnable{
private int ticketNum = 10;
boolean flag = true; //外部停止方式
public void run(){
while(true){
try{
buy();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
//synchronized同步方法,锁的是方法的调用者,锁的是this
private synchronized void buy() throws InterruptedException{
//判断是否有票
if(ticketNum <= 0){
flag = false;
return;
}
//模拟延时
Thread.sleep(1000);
//买票
System.out.println(Thread.currentThread().getName() + " get "+ticketNum--);
}
}
//同步块
public class UnsafeList{
public static void main(String[] args){
List<String> list = new ArrayList<String>();
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());
}
}

浙公网安备 33010602011771号