多线程1

/**
 * 进程:正在进行中的程序(直译)
 * 线程:进程中一个负责程序执行的控制单元(执行路径)
 * 一个进程中可以多执行路径,称之为多线程
 * 一个进程中至少有一个线程
 * 开启多个线程是为了同时运行多部份代码。
 * 每一个线程都有自己运行的内容。这个内容可以称之为线程要执行的任务。
 */
//系统垃圾处理
/**
 * 其实应用程序的执行都是cpu在做着快速的切换完成的。这个切换是随机的。
 * JVM启动时就启动了多个线程,至少有两个线程可以分析得出来。
 * 1.执行main函数的线程
 * 2.负责垃圾回收的线程
 *      代码在垃圾回收器里面定义
 */
class G extends Object{
    public void finalize(){//类的回收方法
        System.out.println("object garbage clone");
    }
}
public class packDemo{
    public static void main(String[] args){
        
        new G();
        new G();
        System.gc();//系统垃圾回收
        new G();
        System.out.println("gello");
    }
}
//运行结果:
//gello
//object garbage clone

多线程
继承Thread类

/**
 * 如何创建一个线程
 * 创建线程方式一:继承Thread类。
 * 步骤:
 * 1,定义一个类继承Thread类。
 * 2,覆盖Thread类中的run方法。
 * 3,直接创建Thread类的子类对象
 * 4,调用start方法开启线程并调用线程的任务
 * 可以通过Thread.getName()获取线程名字
 */
class G extends Thread{
    private String name;
    G(String name){
        this.name = name;
    }
    public void run(){
        show();
    }
    public void show(){
        for(int i=0;i<10;i++){
            System.out.println(this.name+"...i = "+i);
        }
    }
    public void finalize(){//类的回收方法
        System.out.println("object garbage clone");
    }
}
public class packDemo{
    public static void main(String[] args){
        // Thread t1 = new Thread();//创建线程
        /**
         * 创建线程的目的是开启一条执行路径,运行指定的代码和其他代码同时运行。
         * 而运行的指定代码就是这个执行路径的任务
         * jvm创建的主线程的任务都定义在主函数中。
         * 自定义线程的任务:
         * Thread类用于描述线程,run方法封装自定义线程运行任务的函数。
         */
        G g1 = new G("g1");
        G g2 = new G("g2");
        g1.start();//调用run方法
        g2.start();
        System.gc();//系统垃圾回收
        System.out.println(4/0);
        for(int i=0;i<20;i++){
            System.out.println("gello.."+i+"..."+Thread.currentThread().getName());
        }
    }
}

实现Runable接口

/**
 * Thread类不能和其他类同时被继承
 * 创建线程的第二种方式:实现Runable接口
 * 1.定义类实现Runable接口
 * 2.覆盖接口中的run方法,将线程的任务代码封装到run方法中
 * 3.通过Thread类创建线程对象,并将Runable接口的子类对象作为构造函数的参数进行传递
 *      为什么?
 *      因为线程的任务都封装在Runable接口子类对象的run方法中
 *      所以要在线程对象创建时就必须明确要运行的任务
 * 4.调用线程对象的start方法开启线程
 * 
 * 实现Runable接口和继承Thred的区别:
 * 1.实现Runable将线程的任务从线程的子类中分离出来进行了单独封装。
 *      按照面向对象的思想将任务封装成对象
 * 2.实现Runable避免了java单继承的局限性
 */
class Fu{
    public void show(){}
}
class G extends Fu implements Runnable{//通过扩展G类的功能,让其中的内容可以作为线程的任务执行。
                    //通过接口的形式完成
    private String name;
    G(String name){
        this.name = name;
    }
    public void run(){
        show();
    }
    public void show(){
        for(int i=0;i<10;i++){
            System.out.println(this.name+"... = "+i+"..."+Thread.currentThread().getName());
        }
    }
}
public class packDemo{
    public static void main(String[] args){
        G g1 = new G("g1");
        Thread t1 = new Thread(g1);
        Thread t2 = new Thread(g1);
        t1.start();
        t2.start();
    }
}
//Thread类架构
class Thread{
    private Runnable r;
    Thread(){}
    Thread(Runnable r){
        this.r = r;
    }
    public void run(){
        if(r!=null)
            r.run();
    }
    public void start(){
        run();
    }
}

多线程:卖票示例

/**
 * 线程安全问题产生的原因:
 * 1.多个线程在操作共享的数据
 * 2.操作共享数据的代码有多条
 * 当一个线程在执行操作共享数据的代码时,其他线程参与了运算。就会导致线程安全问题的产生。
 * 
 * 解决方式:
 * 将多条操作共享数据的代码封装起来,当有线程在执行代码时,其他线程不能参与运算,
 * 必须要当前线程将代码执行完毕后,其他线程才可以参与运算。
 * 
 * 在java中用同步代码块:
 * synchronized(对象)
 * {需要被同步的代码;}
 * 
 * 同步的好处:解决了线程的安全问题
 * 同步的弊端:相对降低了效率,因为同步外的线程都会判断同步锁
 * 同步的前提:同步中必须有多个线程并使用同一同步锁
 */
class Ticket implements Runnable{
    private int num = 100;
    Object obj = new Object();
    public void run(){
        while(true){
            synchronized(obj)
            {
                if(num>0){
                    try{Thread.sleep(10);}catch(InterruptedException e){}
                    System.out.println(Thread.currentThread().getName()+"...sale..."+num--);
                }
            }
        }
    }
}
public class packDemo{
    public static void main(String[] args){
        Ticket t = new Ticket();//创建一个线程任务对象
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        Thread t3 = new Thread(t);
        Thread t4 = new Thread(t);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

同步函数

/**
 * 需求:两个储户,每个都到银行存钱,每次存100,共存三次
 */
/**
 * 同步函数使用的锁是this,
 * 同步函数和同步代码块的区别:
 * 同步函数的锁是固定的this。
 * 同步代码块的锁是任意的对象。
 * 建议使用同步代码块
 */
class Bank{
    private int sum;
    Object obj = new Object();
    
    //直接同步函数
    public synchronized void add(int num){
        sum = sum+num;
        System.out.println("sum = "+sum);
    }
    /*
    public void add_code(int num){
        synchronized(obj){
            sum = sum+num;
            System.out.println("sum = "+sum);
        }
    }
    */
}
class Cus implements Runnable{
    Object obj = new Object();
    Bank b = new Bank();
    public void run(){
        for(int i=0;i<3;i++){
            b.add(100);
        }
    }
}

public class packDemo{
    public static void main(String[] args){
        Cus c = new Cus();
        Thread t1 = new Thread(c);
        Thread t2 = new Thread(c);
        t1.start();
        t2.start();
    }
}
//public static synchronized void show(){}
//静态方法中没有this,锁是该函数(当前class文件)所属的字节码文件对象(对象)用:this.getClass() or 类名.class表示

单例设计模式涉及的多线程问题

//
//饿汉式
class Single{
    private static final Single s = new Single();
    private Single(){}
    public static Single getInstance(){
        return s;//用到相同数据s的代码只有一条,不用加锁
    }
}
//懒汉式
class Single_lazy{
    private static Single_lazy s = null; 
    private Single_lazy(){}
    public static Single_lazy getInstance(){
        if(s==null){//双重判断,为了减少锁判断,提高效率
            synchronized(Single_lazy.class){
                if(s==null){
                    s = new Single_lazy();
                }
            }
        }
        return s;
    }
}

死锁示例

/**
 * 死锁示例
 * 常见情形之一:同步的嵌套
 */
class Test implements Runnable{
    private Boolean flag;
    Test(Boolean flag){
        this.flag = flag;
    }
    public void run(){
        if(flag){
            synchronized(MyLock.locka){
                System.out.println("if....locka");
                synchronized(MyLock.lockb){
                    System.out.println("if....lockb");
                }
            }
        }
        else{
            synchronized(MyLock.lockb){
                System.out.println("else....lockb");
                synchronized(MyLock.locka){
                    System.out.println("else....locka");
                }
            }
        }
    }
}
class MyLock{
    public static Object locka = new Object();
    public static Object lockb = new Object();
}
public class packDemo{
    public static void main(String[] args){
        Test a = new Test(true);
        Test b = new Test(false);
        Thread t1 = new Thread(a);
        Thread t2 = new Thread(b);
        t1.start();
        t2.start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值