Java的创建和线程安全问题

1.创建线程

  • 创建一个线程的方法:
  • 方法一:继承Thread类
  •  1).创建一个类继承于Thread 类
    
  •  2).重写run 方法
    
  •  3).通过对象的start的方法启动线程,但不能通过run方法来启动线程
    
  • 创建线程方法二 :Runable
  •  1)创建一个类实现Runable接口
    
  •  2)实现抽象run方法
    
  •  3)创建实现类对象,
    
  •  4)将此对象作为参数传递给Thread类的构造器创建Thread类的对象
    
  •  5)通过Thread类对象的start方法启动线程
    
  • 两种方式的比较
  • Runnable优先选择。原因:1.单继承的弊端;2.实现Runnable类方式通过将共享数据放在实现类,更适合共享数据的处理。
    例子:
在这里插入代码片`public class CreatThread {
    public static void main(String[] args) {
        MyThread thrad = new MyThread();

        testafter();
        thrad.start();

        //匿名创建子类的方法
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    if (i % 2 == 0) {
                        System.out.println(i);
                    }
                }

            }
        }.start();


        //通过Runnable来创建线程
        Thread th = new Thread(new RunThread());
        th.start();
        MethodMain();
    }

    public static void testafter() {
        for (int i = 0; i < 500; i++) {
            System.out.println("running in main ");
        }
    }

    private static void MethodMain()
    {
        for (int i = 0; i < 20 ; i++) {
            System.out.println(Thread.currentThread().getName() + i);

        }
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 400; i++) {
            System.out.println("Runing in Thread run");
            System.out.println(Thread.currentThread().getName());

        }
    }
}

class RunThread implements Runnable{
    @Override
    public void run() {
        System.out.println("implement  RunThread run method!");
    }
}

`

2.常用方法

/**

  • start()方法,线程从 新建 状态变成 就绪 状态,等待获得cpu的执行权

  • static Thread.currentThread() //返回当前代码执行的线程(返回对象)

  • getName()获得当前线程的name

  • setName()设置当前线程的name

  • yield()释放当前cpu的执行权

  • join()在线程 A 中调用线程 B 的 join 方法,此时,线程 A 进入阻塞状态,直到线程B执行完才继续执行A线程

  • static void sleep(long millionseconds)阻塞millionseconds毫秒,try-catch

  • isAlive()判断当前线程是否还在执行

  • 线程优先级(cpu执行的概率,而不是先后执行,高优先级的线程抢占低优先级的线程的执行 权)

  •   MAX_PRIORITY = 10
    
  •   NORMAL_PRIORITY = 5 默认
    
  •   MIN_PRIORITY = 1
    
  • 获取设置优先级

  •      >setPriority()
    
  •      >getPriority()
    

3.线程安全问题

以买票程序为例
出现的重票和错票就是线程现象,是一种线程安全问题
当某个线程正在操作共享数据时,但操作还没完成时。另一个线程也来操作共享数据,引起线程不安全

  • 解决措施:
    当一个线程在操作一个共享数据的时候,其他线程不能擦于进来—线程锁
    在Java中用同步机制来解决线程安全问题

  • 方式一:同步代码块

  • synchronize(同步监视器){

  • //需要被同步的代码,即操作共享数据的代码

  • }

  • 思路:

  •  同步监视器即 “锁”,任何一个类的对象都可以来充当锁
    
  •  要求: 多个线程用一个锁
    
  •  评价: 解决了线程安全问题, 但是实质上却是一个单线程, 降低了效率。但还是都是用这个方法
    
  • 1.解决实现Runnable类方式的线程安全问题。

  • 2.结决继承Thread类线程安全问题

  • 方式二:

  • 使用同步方法

  •  1.使用方法解决Runnable实现类方式的线程安全问题
    
  •  2.同步方法解决继承Thread类方式线程安全问题
    

**/

public class ThreadSafe {

    public static void main(String[] args) {
        //实现类方式同步测试
        Windows runnable = new Windows();
        Thread w1 = new Thread(runnable);
        Thread w2 = new Thread(runnable);
        Thread w3 = new Thread(runnable);
        w1.setName("窗口1 ");
        w2.setName("窗口2 ");
        w3.setName("窗口3 ");
        w1.start();
        w2.start();
        w3.start();

        //继承方式同步测试
        HWindow win1 = new HWindow();
        HWindow win2 = new HWindow();
        HWindow win3 = new HWindow();
        win1.setName("窗口1");
        win2.setName("窗口2");
        win3.setName("窗口3");
        win1.start();
        win2.start();
        win3.start();

        //测试同步方法解决Runnable继承类
        IWindow iwin = new IWindow();
        Thread th1 = new Thread(iwin);
        Thread th2 = new Thread(iwin);
        Thread th3 = new Thread(iwin);
        th1.setName("窗口1 ");
        th2.setName("窗口2 ");
        th3.setName("窗口3 ");
        th1.start();
        th2.start();
        th3.start();

        //同步方法--继承方式测试
        HWindow2 win1 = new HWindow2();
        HWindow2 win2 = new HWindow2();
        HWindow2 win3 = new HWindow2();
        win1.setName("窗口1");
        win2.setName("窗口2");
        win3.setName("窗口3");
        win1.start();
        win2.start();
        win3.start();

    }
}

class Windows implements Runnable {
    private int tickets = 100;//不同加static,传递的同一个Windows2
//    private final Object obj = new Object();

    @Override
    public void run() {
//        try {
//            Thread.sleep(500);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        while (tickets > 0) {
//            System.out.println(Thread.currentThread().getName() + "出售票号为:" + tickets);
//            tickets--;
//        }
        //利用线程锁
        while (true) {
            //synchronized (obj)
            synchronized (this){
                if (tickets > 0) {
                    System.out.println(Thread.currentThread().getName() + "出票" + tickets);
                    tickets--;
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else
                    break;
            }
        }


    }
}

/**
 * 继承方式同步问题解决
 **/

class HWindow extends Thread {
    private static int tickets = 100;
    private static final Object obj = new Object();

    @Override
    public void run() {
        while (true) {
            //synchronized (obj)
            synchronized (HWindow.class){
                if (tickets > 0) {
                    System.out.println(getName() + " 出售票号为 :" + tickets);
                    tickets--;
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else break;
            }
        }
    }
}

//使用同步方法解决同步问题
class IWindow implements Runnable{

    private  int tickets = 100;

    @Override
    public void run() {
        while(true){
            sellTickets();
            if (tickets <= 0)
                    break;
        }
    }
//    同步方法,同步监视器为this
    private synchronized  void sellTickets(){
        if(tickets > 0){
            System.out.println(Thread.currentThread().getName() + "出售票号 "+ tickets);
            tickets--;
        }
    }
}

//使用同步方法解决继承方式线程安全问题
class HWindow2 extends Thread{
    private static int tickets = 100;

    @Override
    public void run() {
        while(true){
            sellTickets();
            if(tickets <= 0)
                break;
        }

    }
    //必须为静态方法,监视器为: Hwindow.class
    private static synchronized void sellTickets(){
        if(tickets > 0){
            System.out.println(Thread.currentThread().getName() + "出售票号 "+ tickets);
            tickets--;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

4懒汉式单例模式线程安全方式

lass Bank{
    private static Bank bank= null;
    private Bank(){}
    public static Bank GetInstance(){
        /*
        * 效率较高的一种方式,后面的线程到这个if语句的时候bank已经不是null, 就不再进入等待*/
        if(bank == null) {
            synchronized (Bank.class) {
                if (bank == null) {
                    bank = new Bank();
                }
            }
        }
        return bank;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值