JavaSE-多线程

package com.btp.t4.多线程;

/*
 * 单线程:一条线可以串起来的
 */
public class TestMain{
    public static void main(String[] args){
        method2("btp");
    }

    private static void method2(String str) {
        // TODO 自动生成的方法存根
        System.out.println("method2");
        method1(str);
    }

    private static void method1(String str) {
        // TODO 自动生成的方法存根
        System.out.println("method1");
        System.out.println(str);
    }
}
TestMain
package com.btp.t4.多线程;
/*
 * 创建一个子线程,完成1-100之间自然数的输出。同样地,主线程执行同样的操作
 * 创建多线程的第一种方式:继承Thread类
 */
public class TestThread {
    public static void main(String[] args){
        //3.创建一个子类的对象
        SubThread st=new SubThread();
        //4.调用线程的start()方法:启动此线程;调用相应的run()方法
        st.start();//一个线程对象只能够执行一次start(),可以再创建一个对象
        //st.run();//只调用run().并没有启动此线程
        SubThread st1=new SubThread();
        st1.start();
        for(int i=1;i<=100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

//1.创建一个继承Thread的子类
class SubThread extends Thread{
    //2.重写Thread类的run()方法。方法内实现此子线程要完成的功能
    public void run(){
        for(int i=1;i<=100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}
TestThread
package com.btp.t4.多线程;

public class TestThread1 {
    public static void main(String[] args)
    {
        PrintNum1 p=new PrintNum1();
        Thread t1=new Thread(p);
        Thread t2=new Thread(p);
        t1.start();
        t2.start();
        
    }
}

class PrintNum1 implements Runnable{

    @Override
    public void run() {
        // TODO 自动生成的方法存根
        for(int i=1;i<=100;i++)
        {
            if(i%2==0)System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
    
}
TestThread1
package com.btp.t4.多线程;

public class TestTwoThread {
    public static void main(String[] args){
//        Thread t1=new Thread1();
//        t1.start();
//        t1=new Thread2();
//        t1.start();
        
        new Thread(){
            public void run(){
                for(int i=1;i<=100;i++)
                {
                    if(i%2==0)System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
        }.start();
        new Thread(){
            public void run(){
                for(int i=1;i<=100;i++)
                {
                    if(i%2!=0)System.out.println(Thread.currentThread().getName()+":"+i);
                }
            }
        }.start();
    }
}

class Thread1 extends Thread{
    public void run(){
        for(int i=1;i<=100;i++)
        {
            if(i%2==0)System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}

class Thread2 extends Thread{
    public void run(){
        for(int i=1;i<=100;i++)
        {
            if(i%2!=0)System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}
TestTwoThread
package com.btp.t4.多线程;
/*
 * 继承的方式:模拟火车站售票窗口,开启三个窗口售票,总票数为100张
 * 存在线程安全问题
 */

public class TestWindow {
    public static void main(String[] kobe)
    {
        Window w1=new Window();
        Window w2=new Window();
        Window w3=new Window();
        
        w1.setName("窗口1");
        w2.setName("窗口2");
        w3.setName("窗口3");
        
        w1.start();
        w2.start();
        w3.start();
        
    }
}

class Window extends Thread{
    static int ticket=100;//如果不声明为static,就是300张
    //Object obj=new Object();也不能当锁,三个对象,三把锁
    static Object obj=new Object();//共用一把锁
    public void run(){
        while(true){
            synchronized(obj){//this代表当前对象,而有三个对象,所以创建了3个锁,所以不能使用this
            if(ticket>0){
                try {
                    Thread.currentThread().sleep(100);
                } catch (InterruptedException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"售票,票号为:"+ticket--);
            }else{
                break;
            }
            }
        }
    }
}
TestWindow
package com.btp.t4.多线程;
/*
 * 实现的方式:模拟火车站售票窗口,开启三个窗口售票,总票数为100张
 */
/*
 * 创建多线程的第二种方式:通过实现的方式
 * 1.创建一个实现了Runnable接口的类
 * 2.实现Runnable内的Run()方法
 * 3.创建一个实现类的对象
 * 4.将此对象作为形参传入Thread类的构造器中,创建Thread类的对象,此对象作为一个线程
 * 5.调用start()方法,执行run()
 * 
 * 
 * 对比继承的方式   VS 实现的方式
 * 1.联系:Thread类本身就实现了Runnable接口
 * 2.哪个方式好:实现的方式优于继承的方式
 *     ①实现的方式避免了java单继承的局限性
 *     ②如果多个线程要操作同一份资源(数据),更适合使用实现的方式
 *     
 *     
 *此程序存在线程安全问题,打印车票时,会出现重票,错票
 *1.存在的原因:由于一个线程在操作共享数据的过程中,未执行完毕的情况下,另外的线程参与进来,
 *  导致共享数据存在安全问题
 *2.如何解决线程的安全问题?
 *  必须让一个线程操作共享数据完毕以后,其他线程才有机会参与共享数据的操作
 *3.java如何实现线程的安全:线程的同步机制
 *       方式1:同步代码块
 *           synchronized(同步监视器){
 *           //需要被同步的代码块(即为操作共享数据的代码)
 *           }
 *           1.共享数据:多个线程共同操作的同一个数据(变量)
 *           2.同步监视器:由一个类的对象来充当。哪个线程获取此监视器,谁就执行大括号里被同步的代码。俗称:锁
 *           3.同步监视器可以是任何类的对象 ,要求所有线程共用一把锁
 *       方式2:同步方法
 *            将操作共享数据的方法声明为synchronized。即此方法为同步方法,能够保证当其中一个线程执行此方法时,
 *            其它线程在外等待直至此线程执行完此方法
 *            >同步方法的锁:this
 *4.线程同步的弊端:由于同一个时间只能有一个线程访问共享数据,效率变低了
 */
public class TestWindow1 {

    public static void main(String[] args) {
        //要想启动一个多线程,必须调用start()
        //Runnable接口内并没有start()方法,只有Thread及其子类才有
        //把实现Runnable接口的类的对象传入Thread构造器,通过Thread对象来调用start()
        Window1 w=new Window1();//只有一个Window1对象,所以只有100张票
        new Thread(w).start();
        new Thread(w).start();
        new Thread(w).start();

    }

}


class Window1 implements Runnable{
    int ticket=100;//共享数据
    Object obj=new Object();//监视器:初始是“绿灯”,每次有线程操作共享数据,就变成“红灯”,表示不允许其他线程再去操作共享数据。
                            //只有一个线程操作完这个共享数据,才会转为“绿灯”,再允许其他线程操作
    public void run(){
        while(true){
            //Object obj=new Object();//也不能写在这里,写在这里就是每个线程一把锁
            synchronized(obj){//这里不能写new Object();因为每次new了之后,都生成一把锁,都是“绿灯”,都允许进入。不安全。
            if(ticket>0){
                try {
                    Thread.currentThread().sleep(10);
                } catch (InterruptedException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"售票,票号为:"+ticket--);
            }else{
                break;
            }
            }
        }
    }
    
    //同步方法,然后run()调用此方法就可以了
    public synchronized void show()
    {
        
            if(ticket>0){
                try {
                    Thread.currentThread().sleep(10);
                } catch (InterruptedException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"售票,票号为:"+ticket--);
            }
        
    }
    
}
TestWindow1
package com.btp.t4.多线程;
/*
 * Thread的常用方法:
 * 1.start():启动线程并执行相应的run()方法
 * 2.run():子线程要执行的代码放入run()方法中
 * 3.Thread.currentThread():静态的,调取当前的线程
 * 4.getName():获取此线程的名字
 * 5.setName():设置此线程的名字
 * 6.yield():调用此方法的线程释放当前CPU的执行权
 * 7.join():在A线程中调用B线程的join()方法。表示:当执行到此方法,A线程停止执行,直至B线程执行完毕,
 * A线程再接着join()之后的代码执行
 * 8.isAlive():判断当前线程是否还存活
 * 9.sleep(long l):显式的让当前线程睡眠l毫秒
 * 10.线程通信:wait()  notify()  notifyAll()
 * 
 * 设置线程的优先级:
 * getPriority():返回线程优先级
 * setPriority(ine newPriority):设置线程的优先级:概率变大了,不是百分百
 * 
 */
public class TestThreadMethod {
    public static void main(String[] args){
        SubThread1 st1=new SubThread1();
        st1.setPriority(Thread.MAX_PRIORITY);
        st1.start();
        System.out.println(st1.getName());
        st1.setName("子线程1");
        
        Thread.currentThread().setName("主线程");
        System.out.println(Thread.currentThread().getName()+"!!!!!!!!");
        
        
            for(int i=1;i<=100;i++){
                //if(i%10==0)Thread.currentThread().yield();
                System.out.println("--------"+Thread.currentThread().getName()+":"+i);
                if(i==20)
                    try {
                        st1.join();
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
        }
        
        
        //SubThread1 st2=(SubThread1) Thread.currentThread();//调用的是主线程,报错
        //System.out.println(st2.getName());
        System.out.println(st1.isAlive());
    }
    
}


class SubThread1 extends Thread{
    //2.重写Thread类的run()方法。方法内实现此子线程要完成的功能
    public void run(){
        try {
            Thread.currentThread().sleep(100);
        } catch (InterruptedException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        for(int i=1;i<=100;i++){
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
    
    
}
TestThreadMethod
package com.btp.t4.多线程;
/*
 * 线程通信:如下的三个关键字使用的话,都得在同步代码块和同步方法中
 * wait():一旦一个线程执行到wait(),就释放当前的锁
 * notify()/notifyAll():唤醒wait()的一个/所有的线程
 * 使用两个线程打印1-100,线程1,线程2交替打印
 */
public class TestCommunication {
    public static void main(String[] args){
        PrintNum p=new PrintNum();
        new Thread(p).start();
        new Thread(p).start();
    
    }
}
class PrintNum implements Runnable{
    int  num=1;
    @Override
    public void run() {
        // TODO 自动生成的方法存根
        while(true){
            synchronized(this){
                notify();//唤醒另外一个线程,但由于此时锁是本线程掌握的,所以还是本线程先执行
                if(num<=100){
                    try {
                        Thread.currentThread().sleep(10);
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+":"+num);
                    num++;
                }
                try {
                    wait();//释放本线程的锁和资源,使另外一个线程可以获得
                } catch (InterruptedException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }
            }
        }
    }
    
}
TestCommunication
package com.btp.t4.多线程;

public class Practice {

    public static void main(String[] args) {
        //1.继承的方式
//        Account ac=new Account(0);
//        Customer c1=new Customer(ac);
//        Customer c2=new Customer(ac);
//        c1.setName("账户1");
//        c2.setName("账户2");
//        c1.start();
//        c2.start();
        //2.实现的方式
        Account ac1=new Account(0);
        Customer1 cs=new Customer1(ac1);
        new Thread(cs).start();
        new Thread(cs).start();
    }

}


class Account{
    private int money;

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account [money=" + money + "]";
    }

    public Account(int money) {
        super();
        this.money = money;
    }

    public Account() {
        super();
    }
    public void addMoney(int money){
        this.money+=money;
    }
    
}
//继承的方式
class Customer extends Thread{
    Account ac=null;

    public Account getAc() {
        return ac;
    }

    public void setAc(Account ac) {
        this.ac = ac;
    }

    @Override
    public String toString() {
        return "Customer [ac=" + ac + "]";
    }

    public Customer(Account ac) {
        super();
        this.ac = ac;
    }

    public Customer() {
        super();
    }
    public void addMoney(int money){
        synchronized(Customer.class){
        for(int i=0;i<3;i++){
        try {
            Thread.currentThread().sleep(1000);
        } catch (InterruptedException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        this.ac.addMoney(money);
        System.out.println(Thread.currentThread().getName()+":"+ac.getMoney());
        }
        }
    }
    public void run(){
        addMoney(1000);
    }    
}


//实现的方式
class Customer1 implements Runnable{
    Account ac=null;
    
    public Account getAc() {
        return ac;
    }

    public void setAc(Account ac) {
        this.ac = ac;
    }

    @Override
    public String toString() {
        return "Customer1 [ac=" + ac + "]";
    }

    public Customer1(Account ac) {
        super();
        this.ac = ac;
    }

    public Customer1() {
        super();
        // TODO 自动生成的构造函数存根
    }
    public synchronized void addMoney(int money){
        for(int i=0;i<3;i++){
        try {
            Thread.currentThread().sleep(1000);
        } catch (InterruptedException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        this.ac.addMoney(money);
        System.out.println(Thread.currentThread().getName()+":"+ac.getMoney());
        }
    }
    @Override
    public void run() {
        addMoney(1000);
    }
    
}
Practice
package com.btp.t4.多线程;
/*
 * 死锁
 */
public class TestDeadLock {
    static StringBuffer sb1=new StringBuffer();
    static StringBuffer sb2=new StringBuffer();
    public static void main(String[] args){
        new Thread(){
            public void run(){
                synchronized(sb1){
                    try {
                        Thread.currentThread().sleep(100);
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
                    sb2.append("A");
                    synchronized(sb2){
                        sb1.append("B");
                        System.out.println(sb1.toString());
                        System.out.println(sb2.toString());
                    }
                }
            }
        }.start();
        
        new Thread(){
            public void run(){
                synchronized(sb2){
                    try {
                        Thread.currentThread().sleep(100);
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
                    sb2.append("C");
                    synchronized(sb1){
                        sb1.append("D");
                        System.out.println(sb1.toString());
                        System.out.println(sb2.toString());
                    }
                }
            }
        }.start();
    }
    
}
TestDeadLock
package com.btp.t4.多线程;
/*
 * 关于懒汉式的线程安全问题:使用同步机制
 * 对于一般的方法,使用同步代码块,锁可以考虑使用this
 * 对于静态方法而言,使用当前类本身充当锁:类名.class
 */
public class TestSingletonSecurity {

    public static void main(String[] args) {
        Singleton s=Singleton.returnSingleton();
        Singleton s1=Singleton.returnSingleton();
        System.out.println(s==s1);
    }

}

class Singleton
{
    private Singleton(){
        
    }
    private static Singleton sl=null;
    
    public static Singleton returnSingleton(){
        if(sl==null){
        synchronized(Singleton.class){//使用类本身作为锁,其实还是一个对象 Class cl=Singleton.class;
            
        if(sl==null)sl=new Singleton();//如果一个线程进来,发现s1==null,然后还没有创建对象,就挂起了
                                       //这时候又有一个线程进来,发现此时s1还是null,创建对象,然后这时候
                                       //原先那个线程挂起状态结束,运行,也创建了一个对象,这时候就有2个对象
                                       //就是线程不安全的
        }
        }
        return sl;
    }
}
TestSingletonSecurity
package com.btp.t4.多线程;
/*
 * 生产者/消费者的问题
 * 生产者将产品交给店员,而消费者从店员处拿走产品。店员一次只能持有固定数量的产品,如果生产者
 * 试图生产更多的产品,店员会叫停一下,如果店中有空位了再通知生产者继续生产,如果店中没有产品了,
 * 店员会告诉消费者等一下,如果店中有产品了再通知消费者来取走产品。
 * 
 * 分析
 * 1.是否涉及到多线程的问题?是!生产者和消费者
 * 2.是否涉及到共享数据?有,即为产品数量
 * 3.是否涉及到线程的通信?有。
 */
public class TestProduceConsume {

    public static void main(String[] args) {
        Clerk clerk=new Clerk(0);
        Producter p=new Producter(clerk);
        Consumer c=new Consumer(clerk);
        Thread p1=new Thread(p);
        p1.setName("Producter1");
        p1.start();
//        
//        Thread p2=new Thread(p);
//        p2.setName("Producter2");
//        p2.start();
        
        Thread c1=new Thread(c);
        c1.setName("Consumer1");
        c1.start();
        
        Thread c2=new Thread(c);
        c2.setName("Consumer2");
        c2.start();
        
    }

}

class Producter implements Runnable{//生产者
    Clerk clerk;
    
    public Producter(Clerk clerk) {
    super();
    this.clerk = clerk;
}

    @Override
    public void run() {
        System.out.println("生产者开始生产!");
        while(true){
        clerk.addProduct();
        }
    }
    
}

class Consumer implements Runnable{//消费者
    Clerk clerk;
    
    public Consumer(Clerk clerk) {
    super();
    this.clerk = clerk;
}

    @Override
    public void run() {
        System.out.println("消费者开始消费!");
        while(true){
        clerk.consumeProduct();
        }
    }
    
}

class Clerk{//店员
    int product;
    
    public Clerk(int product) {
    super();
    this.product = product;
}

    public static int PRODUCT=20;//最多持有产品数量 
    public synchronized void addProduct(){//生产产品
        if(product>=PRODUCT){
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
        }else{
            product++;
            System.out.println(Thread.currentThread().getName()+"生产了第"+product+"件产品");
            notifyAll();
        }
    }
    
    public synchronized void consumeProduct(){//消费产品
        if(product<=0){
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
        }else{
            product--;
            System.out.println(Thread.currentThread().getName()+"消费了第"+product+"件产品");
            notifyAll();
        }
    }
}
TestProduceConsume
原文地址:https://www.cnblogs.com/a842297171/p/5199765.html