多线程技术(整理)

进程与线程

线程与进程相似,是一段完成某个特定功能的代 码,是程序中单个顺序控制的流程,但与进程不同 的是,同类的多个线程是共享一块内存空间和一组 系统资源。所以系统在各个线程之间切换时,开销 要比进程小的多,正因如此,线程被称为轻量级进程。一个进程中可以包含多个线程。

  • 进程相当于软件有独立内存空间
  • 线程相当于软件的执行路径
  • 一个软件可以有多个执行路径即进程包含多个线程
  • -每个线程都有自己的栈空间,共享一份堆内存
    线程有同步与异步、高效与低效、安全与不安全
    并发与并行(并发:同一段时间 并行:同一时刻)

线程创建

Java中创建一个子线程涉及到:java.lang.Thread类 和java.lang.Runnable接口
Thread是线程类,创建 一个Thread对象就会产生一个新的线程。而线程执 行的程序代码是在实现Runnable接口对象的run()方 法中编写的,实现Runnable接口对象是线程执行对 象。

线程执行对象实现Runnable接口的run()方法,run() 方法是线程执行的入口,该线程要执行程序代码都 在此编写的,run()方法称为线程体。

//接口Runnanle
public interface Runnable { 
	 public abstract void run();
}
//接口实现
public class Thread implements Runnable{}
//
public class MyThread extends Thread{}

继承Thread线程类

Thread类
构造方法

Thread()
Thread​(Runnable target)
Thread​(Runnable target, String name)

常用方法

getName()//String
getPriority()//int
setPriority​(int newPriority)//void
start()
stop()//不安全过时
sleep​(long millis, int nanos)
setDaemon​(boolean on)


Thread继承实例

public class DemoThread {
    public static void main(String[] args) {
        //Thread线程类
        //创建线程
        MyThread m = new MyThread();
        //开始线程
        m.start();

    }
}

子类

//线程执行对象
/*run方法就是线程要执行的任务方法
 */
public class MyThread extends Thread {

    //这里的代码 就是一条新的执行路径
    //这个执行路径的触发方式不是调用run方法,而是通过thread对象的start()来启动任务
    @Override
    public void run() {
        for(int i = 0;i<10;i++){
            System.out.println("lllllll");
        }
    }
}
//Thread可以用来当匿名内部类
         new Thread(){
             @Override
             public void run() {
                  super.run();
             }
          }.start();

接口Runnable的实现

创建线程Thread对象时,可以将线程执行对象传递 给它

public class DemoRunnable {
    public static void main(String[] args) {
        //实现Runnable
        /*//1. 创建一个任务对象
        MyRunnable m = new MyRunnable();
        //2. 创建一个线程,并为其分配一个任务
        Thread t = new Thread(m);
        */
        Thread t = new Thread(new MyRunnable());
        //3. 执行
        t.start();

    }
}

实现类

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        //线程的任务
        for(int i = 0;i<10;i++){
            System.out.println("jiaijs");

        }
    }
}

实现Runnable 与继成Thread有如下优势:

  • 1.通过创建任务给线程分配的方式来实现多线程,更适合多个线程同时执行相同任务的情况
  • 2.可以避免单继承带来的局限性
  • 3.任务与线程本身是分离的,提高程序的健壮性
  • 4.后续学习的线程池技术,只接受Runnable类型的任务

获取设置线程名

    public static void main(String[] args) throws InterruptedException {
        
        //获取线程名称
        System.out.println(Thread.currentThread().getName());
        //new Thread(new MRunnable()).start();
        Thread t = new Thread(new MRunnable());
        t.setName("线程");
        t.start();

    }
    static class MRunnable implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }

线程的休眠 sleep

Thread.sleep(1000);

线程中断

        //线程的休眠 sleep
        Thread.sleep(1000);

        //线程阻塞/耗时操作

        //线程中断stop过时
        //一个线程是一个独立的执行路径,他是否应该结束,应该由其自身结束
        Thread t1 = new Thread(new MRunnable());
        t1.start();
        for (int i = 0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //给线程t1做中断标记
        t1.interrupt();
    }

        static class MRunnable implements Runnable{
            @Override
            public void run() {
                for (int i = 0;i<10;i++){
                    System.out.println(Thread.currentThread().getName()+i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // e.printStackTrace();
                        System.out.println("发现中断标记");
                        return;//表示自杀
                    }
                }
            }
        }

线程:用户线程和守护线程

    //我们创建的就是用户线程
    //用户线程当一个进程不包含任何存活的用户线程时,进程结束
    // 守护线程用于守护用户线程的,当最后一个用户线程结束时,所有守护线程自动死亡
    //将用户线程转化为守护线程 比如子线程要在start之前转化
    //t1.setDaemon(true);

线程安全

线程不安全

    public static void main(String[] args) {
        //线程不安全问题
        Runnable r = new Ticket();//多态
        new Thread(r).run();
        new Thread(r).run();
        new Thread(r).run();

    }
    static class Ticket implements Runnable{
        private int count = 10;
        @Override
        public void run() {
            while(count>0){
                System.out.println("正在出票");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count--;
                System.out.println("剩余:"+count);
            }
        }
    }

解决方案

//线程同步:synchronized
public class DemoSynchronized {
    public static void main(String[] args) {
        //线程不安全
        //解决方案1:同步代码块
        ///格式:synchronized(锁对象){}
        Runnable r = new DemoThreadSafe.Ticket();//多态
        new Thread(r).run();
        new Thread(r).run();
        new Thread(r).run();

    }
    static class Ticket implements Runnable{
        private int count = 10;
        private Object o = new Object();
        @Override
        public void run() {

                while(true) {
                   // private Object o = new Object();加这里相当于每人一把锁同步代码块就没用了
                    synchronized (o) {
                        if (count > 0) {
                            System.out.println("正在出票");
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            count--;
                            System.out.println(Thread.currentThread().getName()+"剩余:" + count);
                        }else{
                            break;
                        }
                    }
                }
        }
    }
}
public class DemoThreadSafe2 {
    public static void main(String[] args) {
        //2.同步方法代码块
        Runnable r = new DemoThreadSafe.Ticket();//多态
        new Thread(r).run();
        new Thread(r).run();
        new Thread(r).run();
    }
    static class Ticket implements Runnable{
        private int count = 10;
        //显示锁l:fair参数为true为公平锁
        private Lock l = new ReentrantLock(true);

        @Override
        public void run() {

            while(true) {
                boolean flag = sale();
                if(!flag){
                    break;
                }

            }
        }
        public synchronized boolean sale(){
            //锁修饰的方法,锁的是调用它的对象this
            //如果是静态的方法就是 类.calss  即Ticket.class
            if (count > 0) {
                System.out.println("正在出票");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count--;
                System.out.println(Thread.currentThread().getName()+"剩余:" + count);
                return true;
            }
            return false;
        }
    }
}

死锁问题

public class DemoThreadDeath {
    public static void main(String[] args) {
        Culprit c = new Culprit();
        Police p =new Police();
        new MyThread(c,p).start();
        c.say(p);

    }
    static class MyThread extends Thread{
        private Culprit c;
        private Police p;
        public MyThread(Culprit c,Police p){
            this.c = c;
            this.p = p;
        }

        @Override
        public void run() {
            p.say(c);
        }
    }
    static class Culprit{
        public synchronized void say(Police p){
            System.out.println("你放了我,我放了人质");
            p.fun();
        }
        public synchronized void fun(){
            System.out.println("罪犯放走人质,罪犯也放走了");
        }
    }
    static class Police{
        public synchronized void say(Culprit c){
            System.out.println("你放了人质,我放了你");
            c.fun();
        }
        public synchronized void fun(){
            System.out.println("警察救了人质,罪犯跑了");
        }
    }
}

多线程通讯问题

public class DemoWait {
    //多线程通讯问题,生产者与消费者的问题
    public static void main(String[] args) {
        Food f = new Food();
        new Cook(f).start();
        new Waiter(f).start();
    }
    static class Cook extends Thread{
        private Food f;
        public Cook (Food f) {
            this.f = f;
        }

        @Override
        public void run() {
            for(int i =0;i<100;i++){
                if(i%2==0){
                    f.setNameTaste("1","a");
                }else {
                    f.setNameTaste("2","b");
                }
            }
        }
    }
    static class Waiter extends  Thread{
        private Food f;
        public Waiter (Food f){
            this.f= f;
        }

        public void run() {
            for(int i =0;i<100;i++){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                f.get();
            }
        }
    }
    static class Food{
        private String name;
        private  String taste;
        private boolean flag = true;


        public void setNameTaste(String name, String taste) {
            if(flag) {
                this.name = name;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.taste = taste;
                flag=false;
                this.notifyAll();
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        public void get(){
            if(!flag) {
                System.out.println("服务员端菜" + name + taste);
            }
            flag = true;
            this.notifyAll();
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页