码迷,mamicode.com
首页 > 编程语言 > 详细

java多线程

时间:2020-03-15 09:36:38      阅读:48      评论:0      收藏:0      [点我收藏+]

标签:一个   join   之间   stack   程序   start   override   标记   lse   

创建方式:

方式一:继承Thread.

  • 自定义一个类继承Thread类。
  • 重写Thread的run方法,把自定义线程的任务代码定义在run方法上。
  • 创建Thread子类的对象,并且调用start方法启动一个线程。
public class MyThread extends Thread {
    public void run() {
        for (int i = 0; i < 100; i++)
            System.out.println(getName() + i);
    }
}

// test
            MyThread my1=new MyThread();//设置线程名
        MyThread my2=new MyThread();
        my1.setName("线程1 ");
        my2.setName("线程2 ");
        my1.start();
        my2.start();

技术图片

方式二: 实现Runnable接口。

  • 自定义一个类实现Runnable接口。
  • 实现Runnable接口中的run方法,把自定义线程的任务代码定义在run方法上。
  • 创建Runable实现类 的对象。
  • 创建Thread对象,并且把Runnable实现类的对象作为参数传递。
  • 调用Thread对象的start方法开启线程。
public class DeamonDemo implements Runnable{

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

}

// test
public class DeamonTest {
    public static void main(String[] args) {
        DeamonDemo d = new DeamonDemo();
        
        Thread d1 = new Thread(d);
        Thread d2 = new Thread(d);

        d1.start();
        d2.start();

    }
}

守护线程

  • 设置守护线程,一旦主线程结束就结束守护线程
DeamonDemo d = new DeamonDemo();
        
        Thread d1 = new Thread(d);
        Thread d2 = new Thread(d);
                
        d1.setDaemon(true);  //  设置守护线程
        d2.setDaemon(true);
        
        d1.start();
        d2.start();

        for(int i = 0;i<10;i++){
            //打印main线程(主线程)线程名
            System.out.println(Thread.currentThread().getName()+"---"+i);
        }

技术图片

设置线程优先级

  • IllegalArgumentException
  • void setPriority()
  • int getPriority():优先级范围1-10 默认5
        PriorityDemo p = new PriorityDemo();

        Thread tp1 = new Thread(p);
        Thread tp2 = new Thread(p);
        Thread tp3 = new Thread(p);

        tp1.setName("xyg");
        tp2.setName("wdf");
        tp3.setName("OoO");
        
        tp1.setPriority(10);  //  最高优先级
        tp2.setPriority(1);
        tp3.setPriority(1);
        
        tp1.start();
        tp2.start();
        tp3.start();

技术图片

线程join

  • 一旦有join()线程,其他线程必须等待
        JoinDemo p = new JoinDemo();

        Thread tp1 = new Thread(p);
        Thread tp2 = new Thread(p);
        Thread tp3 = new Thread(p);

        tp1.setName("xyg");
        tp2.setName("fuck");
        tp3.setName("wdnmd");

        tp1.setPriority(10);
        tp2.setPriority(1);
        tp3.setPriority(1);

        tp1.start();
        try {
            tp1.join();  //  其他线程等待该线程终止
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        tp2.start();
        tp3.start();

技术图片

线程等待和唤醒

等待唤醒机制:

  • wait() 让线程处于等待状态
  • notify() 唤醒等待的线程
  • wait()的线程被唤醒后,继续执行,wait()方法出现后,对应的线程就释放了锁对象

wait()和sleep()

  • wait()是Object类方法,释放锁对象
  • sleep()是Thread类的的静态方法,不释放锁对象
    public synchronized void set(String name, int age) {
        //如果有数据则等待
        if (flag) {
            try {
                wait();  //  线程等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        //设置值
        this.name=name;
        this.age=age;

        // 修改标记
        flag = true;
        notify();// 线程唤醒
    }
    
        ...

    public synchronized void get(){
        //如果没有数据就等待
        if(!flag){
            try {
                wait();  // 线程等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        System.out.println(name+" "+age);
        
        //修改标记
        flag=false;
        notify();  // 线程唤醒
    }

线程暂停

  • public static void yield()----Thread:暂停当前正在执行的线程,并执行其他线程
  • 使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的
  • 因为让步的线程还有可能被线程调度程序再次选中。
    public void run() {
        for(int i = 0;i<100;i++){
            System.out.println(Thread.currentThread().getName()+"---"+i);
            Thread.yield();  //执行其他线程
        }
    }

线程安全

  •  1是否有共享数据
  •  2是否多条语句操作共享数据
  •  3是否在多线程环境中

    解决方案:

  1. 同步代码块
    synchronized(锁){
    需要被同步的代码
    }
        ...
    public void run() {
            if (x%2==0) {
                //同步代码块
                synchronized (this) {// 多个线程使用同一个锁对象
                    if (ticket > 0) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票。");
                    }
                }
            } 
  1. 同步函数。
    修饰符 synchronized 返回值类型 函数名(形参列表..){
    需要被同步的代码
    }

    public void run() {
            check();
        }
        ...
    //同步方法
    //同步方法的锁对象是this对象
    //静态同步方法的锁对象是 类名.class Class类型对象
    private synchronized void check() {
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "张票。");
            }
    }

注意:

  • 同步代码块的锁可以是任意的对象。 同步函数的锁是固定 的,非静态函数的锁对象是this对象。 静态函数的锁对象是class对象。
  • 锁对象必须是多线程共享的对象,否则锁不住。
  • 在同步代码块或者是同步函数中调用sleep方法是不会释放锁对象的,如果是调用了wait方法是会释放锁对象的。

java多线程

标签:一个   join   之间   stack   程序   start   override   标记   lse   

原文地址:https://www.cnblogs.com/xiongyungang/p/12495740.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!