0826总结

0826总结

疑问

while 的条件里一定是“true”吗?
如下面的两段代码都可以完成作业题2,并且第二种方法当执行完,我们获得想要的结果后可以自动退出运行,第一种还要手动点击停止运行的按钮。

            while (true){
                if (i%2==1&&i<=200){
                    System.out.println(Thread.currentThread().getName()+"---"+i);
                }
                i++;
            }
            while (i<=200){
                if (i%2==1){
                    System.out.println(Thread.currentThread().getName()+"---"+i);
                }
                i++;
            }

知识点

几个概念

并发:在同一个时间段执行两个或者是多个操作 (交替执行)【一人吃两个馒头】
并行:在同一个时刻执行两个或者是多个操作【两个人吃两个馒头】

进程: 正在运行程序,在内存里开辟过空间(任务管理器《ctrl + alt + delete》里面的)
线程:表示每一条执行的路径(如360杀毒里面的 扫描、垃圾清理、修复漏洞同时进行)

进程与线程的关系:一个进程里可以有多个线程,但是一个线程只能存在一个进程里面。

线程分配情况

1、按照时间均匀的分配:两个线程交替执行,以时间为标准(该方式不存在
2、抢占式分配:任意一个线程,谁能够抢到cpu的资源谁就执行(在Java里面就是这种方式)

只执行main 方法:属于单线程,从上到下执行(Java里支持多线程)

实现多线程的方式

1、继承线程类

Thread 类:Java 虚拟机允许应用程序并发地运行多个执行线程
实现的步骤:
1、创建一个Thread 的子类
2、重写 run() 方法 【run方法也就是子线程要执行的操作】
3、实例化这个子类
4、调用 start() 开启线程

//1、2步
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}
//3、4步
    MyThread thread=new MyThread();
    thread.start(); // 只有调用这个方法才会去开辟一条新的路径

注意点
一个线程只能够开启一次,重复开启会产生错误(java.lang.IllegalThreadStateException)

2、实现 Runnable 接口类(常用)

实现的步骤:
1、定义一个类来实现这个接口
2、实现 run() 方法
3、实例化这个实现类
4、实例化一个Thread,传递参数,参数是这个实现类
5、调用 start() 方法

//1、2步
public class Runable implements Runnable {
    @Override
    public void run() {
        for (int i=0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}
//3-5步
public static void main(String[] args) {
    Runable runable=new Runable();
    Thread thread=new Thread(runable);
    thread.start();
}

好处:
1、解决Java单继承的问题
2、可扩展性增强,实现申明与调用的分离,降低了耦合度
3、继承 Thread 实现了这个接口

实现多线程的效率:
对于整个系统来说,效率是提高,但是对于具体的某一个线程,效率就是降低

3、使用类名内部来实现多线程

第一种:Thread thread = new Thread(new Runnable() {}
第二种:Runnable runnable = new Runnable() {}

线程中的一些方法

返回对当前正在执行的线程对象的引用(也就是当前线程):currentThread()

获取线程的名称:getName()

设置线程的名称:setName(String name)【一定要在开启线程之前进行设置,可以通过构造的方式来设置线程的名称】
让当前线程睡一会(停止),别的线程可以执行了:sleep(long millis)

设置线程的优先级:setPriority(int newPriority)【最小是1 默认是5 最大是10,注意:设置优先级不一定是最先执行,只是优先执行的机遇更大一点

join():如果有两个线程: A线程 调用了join方法, A线程执行完成之后,B线程才能执行
注意:1、这个方法必须在线程开启之后进行调用;2、这个方法底层还是调用了wait()方法

礼让:yield(); 如果有两个线程: A线程 调用了yield()方法,b线程不一定就会执行

守护线程:setDaemon(boolean on); 如果有两个线程: A是被守护线程,B守护线程; 如果A终止了,B线程也会终止
判断其是否为守护线程:isDaemon()

避免多线程同时抢占资源的方案
1、同步代码块

关键字:synchronized
语法:synchronized (){}
() 跟的是对象(这个对象可以是任意的对象
{} 跟的是会出现共享数据问题的代码

 synchronized (obj){
    if (count>0){
        System.out.println(Thread.currentThread().getName()+"\t"+"购买了第"+count+"张票");
        count--;
    }
}

注意:三个对象必须是这个锁对象(锁对象:保证只有一个线程进入)

2、同步方法

步骤:
1、把可能出现数据问题的代码抽取成一个方法
2、给方法加上锁的关键字

    @Override
    public void run() {
        show();   //同上1
    }
3、使用Lock

Lock 是一个接口,实现并提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作;此实现允许更灵活的结构
常规的两个方法:
获取锁:lock()
释放锁:unlock()

步骤:
1、实例化这个对象
2、在同步可以出现数据异常的头部调用其lock()
3、在同步可以出现数据异常的尾部加上 unlock() (不常用)

 @Override
    public void run() {
        while (true){
            try {
                l.lock();
                    if (count>0){
                        System.out.println(Thread.currentThread().getName()+"\t"+"购买了第"+count+"张票");
                        count--;
                    }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                l.unlock();
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值