2021-06-08

#java线程
##创建线程的方式
###方法一、继承thread类
一、继承Thread类,重写其run方法,再调用start方法开启此线程,
start方法先启动当前线程,调用其run方法,

注意点:

1、直接调用run方法将不会开启线程,相当于直接创建对象调用方法

2、重复启动一个线程将会报异常,原因:在县城第一次启动时,状态值为0;启动后会修改

3、想要开启多个线程,需创建多个对象,调用其start方法

###方法二、实现Runnable接口
实现Runnable接口,重写run()方法

把实现了Runnable的类作为一个参数构造一个Thread类,
调用start()启动线程

class Window implements RunnableWindow w1 = new Window();

        Thread t1 = new Thread(w1);
        t1.start();

###方法三、实现Callable接口
实现Callable接口,重写call()方法,
把实现了Runnable的类作为一个参数构造一个FutureTask类
将FutureTask类对象作为一个参数构造一个Thread类,再调用start()启动线程
####实现Callable接口更强大
1.call可以有返回值
2.可以抛出异常,被外面捕获
3.支持泛型

###方法四、使用线程池
好处:
1.提高响应速度
2.降低资源消耗
3.设置线程池属性,便于线程管理
可以设置线程池的大小、最大连接数量、超时时间

创建一个设定初始大小的线程池

class  Number implements Runnable;
class  Number1 implements Runnable
public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(10);//创建线程池
        service.execute(new Number());//适用于Runnable接口,执行线程
        service.execute(new Number1());//适用于Runnable接口,执行线程

//        service.submit();适用于Callable接口

        service.shutdown();//关闭线程池
    }

####获取返回值
把实现了Runnable的类作为一个参数构造一个FutureTask类,再调用其get方法获取返回值

class NumThread implements Callable{

    @Override
    public Object call() throws Exception {
        Integer sum = 0;
        for (int i =0;i<101;i++){
            sum+=i;
            System.out.println(i);
        }
        return sum;
    }
}

public class ThreadNew {

    public static void main(String[] args) {
        NumThread numT = new NumThread();
        FutureTask futureTask = new FutureTask(numT);

        new Thread(futureTask).start();
        try {
            //get()获取返回值
            Object sum = futureTask.get();
            System.out.println("总和为:"+sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}

####线程方法:

测试Thread的常用方法

start()启动当前线程,调用其run方法

run(),重写Thread的方法,该线程所做的操作代码写在里面

currentThread(),静态方法返回当前线程的代码

this.yield();释放当前线程的CPU的执行权

join();在线程A中调用线程B的join方法,线程A进入阻塞状态,直到线程B执行完毕,线程A才结束阻塞状态

stop:强制结束线程的生命周期,已经过时。。

sleep(long sillitime)让指定的线程“睡眠”sillitime毫秒数,在sillitime指定的毫秒内,该线程为阻塞状态

isAlive()返回线程的当前状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t4ua10ym-1623132330225)(img.png)]

####线程的生命周期
新建,就绪,运行,阻塞,消亡
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gJ3uyJpA-1623132330228)(img_1.png)]

####线程同步问题
当多个线程同时操作一个共享数据,就会出现同步问题
#####方法一、同步代码块

private Integer piao = 1000;
    Object o = new Object();
    @Override
    public void run() {
        while (true) {
            synchronized (o) {
                if (piao > 0) {
                    System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + piao);
                    piao--;
                } else {
                    break;
                }
            }
        }
    }

用synshronized(Object obj){代码块}
锁对象必须唯一,多个线程必须使用同一把锁

在实现Runnable接口的多线程中,可以考虑用this充当同步监视器

在继承Thread类的多线程中,可以考虑用this.class充当同步监视器

操作一个线程时,其他线程都等待,进入就绪状态
#####方法二、同步方法
当同步的代码块刚好全部在方法中是,我们可以把synchronized放在方法上

    public synchronized void show(){
        if (piao > 0) {
        System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + piao);
        piao--;
        }
    }

该方法默认以this充当同步监视器

用以解决继承Thread的线程的方法时需把方法设置为static,以this.class充当同步监视器

静态方法的同步方法的同步监视器:this.class
非静态方法的同步方法的同步监视器:this

#####解决方式三、lock锁

class Lock1 implements Runnable{
    private Integer ticket = 100;
    private ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {

        while (true){

            try{
                lock.lock();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(ticket>0){
                    System.out.println(Thread.currentThread().getName()+"售票,票号为:"+ticket);
                    ticket--;
                }
            }finally {
                lock.unlock();
            }

        }
    }
}

###死锁
不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源锁,就造成了死锁现象

不会出现异常,不会出现提示,

###线程通行

wait():使当前线程进入阻塞状态,并释放同步监视器

notify():唤醒一个wait()的线程,如果有多个,那就唤醒一个优先级高的

notifyAll():唤醒所有wait()的线程,

wait(),notify(),notifyAll()三个方法必须存在于同步代码块或者同步方法中

wait(),notify(),notifyAll()的调用者必须是同步代码块或者同步方法中的同步监视器

wait(),notify(),notifyAll()这三个方法定义在Object类中

##面试题
###lock锁和synchronize有什么异同
lock.lock()–加锁

lock.unlock()–解锁

相同:都可以解决线程的安全问题

不同:synchronize是自动释放锁,lock锁是需要自己开启和关闭同步监听器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kI5vL8Xa-1623132330231)(img_2.png)]

###sleep()和wait()的异同
####相同:
都是使当前线程进入阻塞状态

####不同:
声明不一样:sleep声明在Thread类中,wait声明在Object类中

调用要求不一样:sleep可以在任何需要的时候调用,wait必须在同步代码块或者同步方法中调用

是否释放同步监视器:sleep–不释放,wait–释放。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值