多线程学习总结知识点

进程
在这里插入图片描述
线程
在这里插入图片描述
线程的调度
在这里插入图片描述
主线程
在这里插入图片描述

public class Therad01 {

public static void main(String[] args) {
    //1.创建一个Thread类的子类
    class MyThread extends Thread {
        //在Thread类的子类中重写Thread类中的run方法
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                System.out.println("run:" + i);
            }
        }
    }
    //3创建Thread类的子类对象
    MyThread mt = new MyThread();
    //4.调用Thread类中的方法start方法,开启新的线程,执行run方法
    mt.start();
    //主线程会继续执行主方法中的代码
    for (int i=0;i<20;i++){
        System.out.println("run:"+i);

    }
}

}

在这里插入图片描述
在这里插入图片描述
public class Thread02
{

public static void main(String[] args) {
    //定义子类的对象
    Mythread02 my = new Mythread02();
    //调用start()方法启动线程
    my.start();
      new Mythread02().start();
      new Mythread02().start();
      new Mythread02().start();
}

import javax.print.DocFlavor;

/*
获取线程的名称:
1.使用Thread类中的方法getName()
String getName()返回线程的名称
2.可以先获取到当前正在执行的线程,使用线程中的方法getName()获取线程的名称
static Thread currentThread()返回当前正在执行的线程对象的引用
*/
//定义一个Thread类的子类
public class Mythread02 extends Thread
{
//重写Thread类子类中的run()方法

@Override
public void run() {
    //获取线程名称

    //String name = getName();
    //System.out.println(name);
    Thread t = Thread.currentThread();
    System.out.println(t);
    String name = t.getName();
    System.out.println(name);
    //链式编程
    System.out.println(Thread.currentThread().getName());

}

}

/*
设置线程的名称:(了解)
1.使用Thread类中的setName(名字)
void setName(String name)改变线程名称,使之与参数name相同
2.创建一个带参数的构造方法,参数传递线程名称,调用父类的带参构造方法,把线程名称传递给父类,让父类(Thread)给子线程起一个名字
Thread(String name)分配新的Thread对象
*/
public class Mythread extends Thread{

public Mythread(){
}
public Mythread (String name){
super(name);//把线程名称传递给父类,让父类(Thread)给子线程起一个名字
}//super可用于在子类构造方法中调用父类的构造方法

@Override
public void run() {
    //获取线程名称
    System.out.println(Thread.currentThread().getName());
}

}
public class dome01 {

public static void main(String[] args) {
    //开启多线程
    Mythread mt=new Mythread();
    mt.setName("小王");
    mt.start();
    //开启多线程
    new Mythread("小李").start();
}

}

/*
public static void sleep(long millis):使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)
毫秒结束后,线程继续执行
*/
public class Deom {

public static void main(String[] args) {
    //模拟秒表
    for (int i=1; i<= 60; i++) {
        System.out.println(i);
        //使用Thread类中的sleep方法让程序睡眠1秒钟
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    }
}

Runable接口
/创建一个Runnable接口的实现类

public class Runnable01 implements Runnable{
//在实现类中重写Runnable接口的run方法,设置线程任务

@Override
public void run() {
    for (int i=0;i<10;i++){
        System.out.println(Thread.currentThread().getName()+"-->"+i);


    }
}

}

/*
实现步骤
1.创建一个Runnable接口的实现类
2.在实现类中重写Runnable接口的run方法,设置线程任务
3.创建一个Runnable接口的实现类对象
4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
5.调用Thread类中的start方法,开启新的线程执行run方法

实现Runnable接口创建多线程程序的好处
1.避免了单继承的局限性
一个类只能继承一个类(一个人只能有一个亲爹),类继承了Thread类就不能继承其他的类
实现了Runable接口,还可以继承其他的类,实现其他的接口
2.增强了程序的扩展性,降低了程序的耦合性(解耦)
实现Runable接口的方式,把设置线程任务和开启新的线程进行了分离
实现类中,重写了run方法,用来设置线程任务
创建Thread类对象,调用start方法,用来开启新线程
*/
public class Demo {

public static void main(String[] args) {
    //3.创建一个Runnable接口的实现类对象
    Runnable01 run = new Runnable01();
    //4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
    Thread t = new Thread(run);
    //5.调用Thread类中的start方法,开启新的线程执行run方法
    t.start();

    for (int i = 0; i < 10; i++) {
        System.out.println(Thread.currentThread().getName() + "-->" + i);

//返回对当前正在执行的线程对象的引用currentThread
}
}
}

匿名内部类与线程
/

匿名内部类方式实现线程的创建
匿名:没有名字
内部类:写在其他类内部的类
匿名内部类的作用:简化代码
把子类继承父类,重写父类的方法,创建子类对象合成一步完成
把实现类实现类接口,重写接口中的方法,创建实现类对像合成一步完成
匿名内部类的最终产物:子类/实现类对象,而这个类没有名字

格式:
new父类/接口(){
重复父类、接口中的方法
}
*/

public class NiMing{

public static void main(String[] args) {
    
    //线程的父类是Thread
    //new MyThread().start();
    new Thread() {
       
        //重写run方法,设置线程任务

        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                System.out.println(Thread.currentThread().getName() + "-->" + "黑马");

            }
        }
    }.start();
    //线程的接口Runanble
    //Runnable r=new Runnable01();//多态
    Runnable r= new Runnable() {
        @Override
        //重写run方法,设置线程任务
        public void run() {
            for (int i = 0; i < 20; i++) {
                System.out.println(Thread.currentThread().getName() + "-->" + "程序员");

            }
        }

    };

new Thread®.start();
//简化接口的方式

    new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                System.out.println(Thread.currentThread().getName() + "-->" + "搬运工");
            }
            }
    }).start();
}

}*

线程安全概述
在这里插入图片描述****
**卖票案例代码实现
*/
卖票案例 有问题
*/
public class Runnable02 implements Runnable
{

private  int ticket=100;
@Override
public void run() {
    //判断是否有票

    while (true){
       if (ticket>0){
           System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
           ticket--;
       }
   }

}

}
public class MaiPiao
{

 public static void main(String[] args)   {
     Runnable02 r =new Runnable02();

     Thread t0 =new Thread(r);
     Thread t1=new Thread(r);
     Thread t2=new Thread(r);
     t0.start();
     t1.start();
     t2.start();

 }

}

在这里插入图片描述
卖票问题解决代码

/*
卖票案例
卖票案例出现了线程安全问题
卖出了不存在的票和重复的票

解决线程安全问题的一种方案;使用同步代码块
格式 :
synchronized (锁对象){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
注意:1.通过代码块中的锁对象,可以使用任意的对象
2.但是必须保证多个线程使用的锁对象是同一个
3.锁对象作用:
把同步代码块锁住,只让一个线程在同步代码块中执行

*/
public class Runnable02 implements Runnable {

//定义票
private int ticket = 100;
//创建一个锁对象
Object obj = new Object();

@Override
public void run() {
    //判断是否有票
    //使用死循环,让卖票操作重复执行
    while (true) {
        //同步代码块
        synchronized (obj) {
            if (ticket > 0) {
                //提高安全问题出现的概率,让程序睡眠
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
                ticket--;
            }
        }
    }
}

}
public class MaiPiao {

 public static void main(String[] args) {
     Runnable02 r =new Runnable02();

     Thread t0 =new Thread(r);
     Thread t1=new Thread(r);
     Thread t2=new Thread(r);
     t0.start();
     t1.start();
     t2.start();

 }

}

同步代码块原理
在这里插入图片描述

同步方法
/*
卖票案例
卖票案例出现了线程安全问题
卖出了不存在的票和重复的票

解决线程安全问题的二种方案;使用同步方法
使用步骤:1.把访问共享数据的代码抽取出来,放到一个方法中
2.在方法上添加synchronized修饰符
格式:定义方法的格式
修饰符 synchronized 返回值类型 方法名(参数列表){
可能会出现线程安全问题的代码(访问了共享数据的代码)
}
*/
public class Runnable02 implements Runnable {

//定义票
private int ticket = 100;
//创建一个锁对象
Object obj = new Object();

@Override
public void run() {

   System.out.println("this"+this);
    //使用死循环,让卖票操作重复执行
    while (true) {
        //同步代码块
       payTicke();
    }
    }
 /*
 定义一个同步方法
 同步方法也会把方法内部的代码锁住
 只让一个线程执行
 同步方法的锁对象是谁?
 就是实现类对象 new Runnable02()
 也就是this

  */
  public synchronized  void payTicke(){
            if (ticket > 0) {
                //提高安全问题出现的概率,让程序睡眠
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
                ticket--;
            }
        }
    }

public class MaiPiao {

public static void main(String[] args) {
     Runnable02 r =new Runnable02();
    System.out.println("r"+ r);
     Thread t0 =new Thread(r);
     Thread t1=new Thread(r);
     Thread t2=new Thread(r);
     t0.start();
     t1.start();
     t2.start();

 }

}
在这里插入图片描述

Lock锁

/*
卖票案例
卖票案例出现了线程安全问题
卖出了不存在的票和重复的票

解决线程安全问题的三种方案;使用Lock锁
java.util.concurrent.Locks.Lock接口
Lock实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作
Lock接口中的方法:
void Lock()获取锁
void unLock()释放锁
java.util.concurrent.Locks.ReentranrLock implements Lock接口

使用步骤:
1.在成员位置创建一个ReentranrLock对象
2.在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
3.在可能会出现安全问题的代码前调用Lock接口中的方法unLock释放锁
*/
public class Runnable02 implements Runnable {
//定义票
private int ticket = 100;
//1.在成员位置创建一个ReentranrLock对象
Lock l = new ReentrantLock();
public void run() {

    System.out.println("this" + this);
    //使用死循环,让卖票操作重复执行
    while (true) {
        l.lock();
        if (ticket > 0) {
            //提高安全问题出现的概率,让程序睡眠
            try {
                Thread.sleep(10);
                System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
                ticket--;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                //  3.在可能会出现安全问题的代码前调用Lock接口中的方法unLock释放锁
                l.unlock();//无论程序是否异常,都会把锁释放掉
            }

        }

    }
}

/* @Override
public void run() {

    System.out.println("this" + this);
    //使用死循环,让卖票操作重复执行
    while (true) {
   l.lock();
        if (ticket > 0) {
            //提高安全问题出现的概率,让程序睡眠
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
            ticket--;
        }
      //  3.在可能会出现安全问题的代码前调用Lock接口中的方法unLock释放锁
        l.unlock();
    }
}
*/

}

public class MaiPiao {

public static void main(String[] args)  {
     Runnable02 r =new Runnable02();
    System.out.println("r"+ r);
     Thread t0 =new Thread(r);
     Thread t1=new Thread(r);
     Thread t2=new Thread(r);
     t0.start();
     t1.start();
     t2.start();

 }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值