java线程

1.线程基础

1)用户线程和主线程main线程的区别:

  • 主线程停掉之后,用户线程不会跟着停掉。
  • 守护线程会随着主线程停掉之后 停掉。

2)不需要结果返回就叫异步执行,需要结果的返回叫同步(需要步调一致)。

3)

  • 多核cpu可以并行执行多个线程,提升效率。但线程太多,会影响cpu资源调度,会影响效率。
  • 单核cpu是串行执行,会比较浪费时间。单核cpu上运行多个程序,实际上是并不是并行执行,而是cpu进行快速的切换,让我们觉得是并行运行的。

2.线程创建方式

1.继承Thread方式(不推荐)
2.匿名内部类方式
3.实现Runable接口方式
4.FutureTask方式(可以获得线程返回结果)

1.实现接口方式:

public class RunableClass implements  Runnable {
    @Override
    public void run() {
        System.out.println (Thread.currentThread ().getName ()+"正在运行");
    }
    
}

2.FutureTask方式,实现Callable接口:

class  CallableTest  implements Callable {


    @Override
    public String call() throws Exception {
        String s="sssss";
        return  s;
    }
}



测试类

public class ThreadTest {


    public static void main(String[] args) throws Exception {
      		//1.匿名内部类方式
        Thread t1=new Thread (){
            @Override
            public void run() {
                System.out.println ("t2开始运行");
            }
        };
      	t1.start();
      	
      	//2.实现接口方式
      	RunableClass r=new RunableClass();
      	Thread t2=new Thread(r);
      	t2.start();
      }
		
	//3. FutureTask方式 
	  CallableTest callable= new CallableTest ();
        FutureTask<String> task = new FutureTask<String> (callable);
        Thread t3 = new Thread (task);//task对象传参给Thread构造线程
        t3.start ();//开始执行
        System.out.println (task.get ());//获取返回的结果为 sssss
      
}

3.join线程同步

使用join方法,保持线程间的同步。
即一个线程代码运行完之后,才运行下一个线程。

Thread t1=new Thread(RunableClass);
t1.join()//t1线程运行结束后才会运行后面的代码
t1.join(2000);//t1运行2s后,运行后面的代码。若t1 2s内就运行完了 也会继续向后运行 不会等2s

4.interupted

Thread.interrupted () 使打断线程,然后可以根据打断标记做后续处理。与之类似的是 Thread.stop()强制关闭线程(不推荐)

打断sleep,wait,join等状态的线程,会抛出InterruptException异常,打断标记会被清除,isInterrupted判断是不是被打断,可根据这个控制什么时候退出线程。

举例:
设计模式之两阶段终止模式:如果被打断之后,后续处理;没被打断,判断是否异常,异常就设置打断标记,无异常就执行记录。
两阶段终止模式

实现Runable接口:

class InterRupted implements  Runnable{

    @Override
    public void run() {
        while (true){
            Thread thread = Thread.currentThread (); 
            //如果被打断  就处理后续一些事 并退出线程
            if(thread.isInterrupted ()){
                System.out.println ("记录日志,退出线程");
                break;
            }

            //没被打断的话
            try {
                Thread.sleep (2000);//睡眠中被打断会被捕获异常 并清除打断标记
                System.out.println ("继续监视,执行监控记录"); 
            } catch (InterruptedException e) {
                e.printStackTrace ();
                 System.out.println ("打断标记:"+thread.isInterrupted ());
                thread.interrupt ();//再次 打断 设置打断标记为true 
            }
        }
    }
}

测试类:

public class InterruptedTest {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread (new InterRupted (),"t1");
        thread.start ();
        thread.sleep(10000); //10秒后打断
        thread.interrupt ();//打断
    }
}

结果分析:
我们看结果,抛出了打断异常,此时打印了 打断标记为false。意思是打断sleep,wait等状态的线程,会抛出打断异常,而且打断标记会被清除。
在这里插入图片描述

4.线程安全

  • 多线程对共享资源操作,线程出现交错情况下,就会出现问题。
  • 一块代码存在对共享资源的多线程读写操作,就是临界区。
    (共享资源 在几个线程都操作)
解决办法:
  • 阻塞时方式:synchronzied 加 锁
  • 非阻塞时方式:原子操作

对临界区的共享资源synchronzied枷锁,使之互斥,可避免线程安全问题。

1.synchronzied加锁实质是保护了synchronzied内的代码块的原子性,这些操作不会被多个线程分拆。

2.synchronzied加在方法上,等同于所在当前对象this枷锁。锁只能锁对象。

public void sell(int count){
    synchronzied(this){
         this.amount-=count;
    }
}

3.如果组合出现两个不同的临界区,需要给两个分别加上锁,因为锁只能锁住相应的对象。

public  void sell(int count,Student s){
        synchronzied(obj1){
             this.amount-=count;
        }         
        synchronzied(obj2)
        {
         s.count++;   
        }
         
}

也可找出两个临界区都共享的对象,进行枷锁。

public  void sell(int count,Student s){
        synchronzied(公共对象){
         this.amount-=count;
         s.count++;  
        }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值