首页 > 编程语言 > 详细

Java多线程

时间:2021-06-24 22:40:15      阅读:22      评论:0      收藏:0      [点我收藏+]

process 和 Thread

  • 程序是指令和数据的有序集合,本身没有含义,是一个静态的概念。
  • 进程则是执行程序的一次过程。是个动态的概念,是系统资源分配的单位。
  • 一个进程可以包括多个线程,至少偶一个线程,不然没有存在的意义。线程是CPU调度和执行的单位。

  很多多线程是模拟出来的,真真的多线程是指由多个CPU即多核。

  模拟出来的多线程只是同一时间点,cput只能执行一个代码,因为切换快,所以有同时执行的错觉

 

 三种创建方式

  继承Thread类

    

class primeTHread extends Thread {
  
public void run(){
    // run 方法线程体 ... }
   }
public static void main (String [] args) {
   // 创建线程对象

primeTHread t = new primeTHread ();
   t.start();
}

  线程开启不一定立即立即执行,根据cpu调度安排。

  实现Runnable接口

    

public class TestThrread3 implements Runnable {
   public void run(){
   
 }

    public static void main(String [] args) {
       // 创建runnable接口的实现类对象
       TestThread3 testThread3 = new TestTrhread3();
       Thread t1 = new Thread(testThread3 );
       t1.start();
  }   
}

  推荐使用实现runnable接口方式创建线程

多个线程同时操作一个数据会造成

  实现Callable接口

    可以定义返回值,可以抛出异常

public class TestThrread4 implements callable<Boolean>{
   public Boolean call() {
   
    return true;
 }

    public static void main(String [] args) {
       // 创建runnable接口的实现类对象
       TestThread4 t4= new TestTrhread4();
        

        //创建执行服务:
        ExecutorService ser = Executors.newFixedThreadPool(1);
        // 提交执行
        Future<Boolean> r1 = ser.submit(t4)
        // 获取结果
        boolean rs1 = r1.get();
        // 关闭服务
        ser.shutdownNow();
  }   
}     

 

多线程操作

public class TestThread1 implements Runnable{
    private int ticketNum = 10;
    @Override
    public void run(){
        while(true) {
            if (ticketNum<=0) {
                break;
            }
            System.out.println(Thread.currentThread().getName() +"----get----"+ ticketNum +"---ticket---");
            try{
                Thread.sleep(200);
            }catch(Exception e){
                System.out.println("error");
            }
            ticketNum--;
        }
    }
    
    public static void main(String [] args) {
        TestThread1 t1 = new TestThread1();
        new Thread(t1,"jack").start();
        new Thread(t1,"roll").start();
        new Thread(t1,"marry").start();
    }
}

多线程操作会发生异常,同一份数据被多个人使用了。

技术分享图片

 

 

 

静态代理模式

  Thread 的底层原理也是静态代理模式

  真实对象和目标代理兑现都要实现同一个接口。代理对象要代理真实角色。真实对象专注做自己的事情,代理对象则负责帮忙处理其他事情。

package staticProxy;

public class Person implements Marry{
    @Override
    public void happyWedding() {
        System.out.println("xxx结婚");
    }
}
package staticProxy;

public class StaticProxy {
    public static void main(String[] args) {
        WeddingCompany wc = new WeddingCompany(new Person());
        wc.happyWedding();
    }
}
package staticProxy;

public class WeddingCompany implements Marry{
    Person person;
    public WeddingCompany(Person person) {
        this.person = person;
    }

    @Override
    public void happyWedding() {
        before();
        person.happyWedding();
        after();
    }

    private void after() {
        System.out.println("结账");
    }

    private void before() {
        System.out.println("布置婚礼");
    }
}
package staticProxy;

public interface Marry {
    void happyWedding();
}

运行结果:

技术分享图片

 

 

 lambda 表达式

  可以避免匿名内部类定义过多,让代码变得很简洁。去掉了没有意义的代码,只留下核心代码。

  函数式接口

    任何接口只包含唯一一个抽象方法,name他就是函数式的接口。

  

package lambda;

public class testLambda {
    public static void main(String[] args) {
        like l =  (int a)-> {
                System.out.println(a + "喜欢钱");
            };

        l.iLike(1);
    }
}

interface like{
    void iLike(int a);
}

 

线程状态

  1. new   新生状态      new Thread() 创建时就进入新生状态
  2. 当调用start()方法  立即进入就绪状态,但不意味立即调度执行
  3. 通过cpu调度,则进入运行状态。运行状态时候如果调用sleep,wait或同步锁,线程则进入阻塞状态,阻塞事件解除后重新进入就绪状态,等待cpu调度。
  4. 线程中断或者结束一旦进入死亡状态就不能再次启动。

  

  方法

setPriority(int newPriority)  更改线程的优先级。
static void sleep(long millis) 在指定毫秒数让当前执行的线程休眠
void join 等待该线程终止。
static void yield() 暂停当前正在执行的线程,并执行其他线程。
void interrupt 中断线程,最好别用。
boolean isAlive()  测试线程是否活动状态

 

    停止线程

      不推荐使用stop()、destroy()方法。推荐线程自己停止。使用标志位终止变量。

package thread;

public class testStop implements Runnable{
    private boolean flag = true;
    @Override
    public void run() {
        int i = 0;
        while (flag) {
            System.out.println("run 线程运行中--" + i++);
        }
    }

    public void stop() {
        this.flag = false;
    }

    public static void main(String[] args) {
        testStop t1 = new testStop();
        new Thread(t1).start();
        for (int j = 0; j < 120; j++) {
            System.out.println("main线程运行中--" +j);
            if (j == 100) {
                t1.stop();
                System.out.println("run停止");
            }
        }
    }
}

    线程休眠sleep

      Thread.sleep(1000);

      每个对象都有一个锁,sleep不会释放锁;

      sleep可以模拟网络延时,倒计时等。

      sleep时间到达之后线程进入就绪状态。

      sleep存在异常InterruptedException;

 

     线程让步yield

      Thread.yield ();

      让当前正在执行的线程暂停,但不阻塞。

      让线程从运行状态转为就绪状态

       线程让步不一定成功。

     线程合并Join

      可以想象成vip插队,等待此线程执行完成之后再执行其他线程,其他线程阻塞。

 

    线程优先级

      getPriority()

      setPriority(int xxx)

      设置线程优先级并不能百分百保证优先执行,只是提高概率。

      要先设置优先级再执行

    守护线程

      线程分为用户线程守护线程  

      虚拟机必须确保用户线程执行完毕

      虚拟机不用等待守护线程执行完毕

      如:后台记录操作日志,监控内存,垃圾回收等待...

package thread;

public class Testdaemon {
    public static void main(String[] args) {
        user u = new user();
        damon d = new damon();
        Thread t1 = new Thread(d);
        t1.setDaemon(true);
        t1.start();

        Thread t2 = new Thread(u);
        t2.start();
    }
}

class user implements Runnable{

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

class damon implements Runnable{

    @Override
    public void run() {
        while (true) {
            System.out.println("----damon----");
        }
    }
}

用户线程结束后,守护线程执行自动停止。

 

    线程同步

      synchronzied

      防止并发状况下保证数据在方法中被访问时的正确性,加入锁机制  synchronzied。

      必须拿到锁之后才能执行,否则就会阻塞。

      同步方法的弊端:会影响性能

      

package thread;

public class Sync  implements Runnable{
    private int ticketNum = 10;
    private  boolean flag = true;

    @Override
    public void run() {
        while (flag) {
            try {
                buy();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
    // 锁的是this
    public synchronized void buy() throws InterruptedException {
        if(ticketNum <= 0) {
            flag = false;
            return;
        }
        Thread.sleep(100);
        System.out.println(Thread.currentThread().getName() +  "拿到了" + ticketNum--);
    }

    public static void main(String[] args) {
        Sync s = new Sync();
        new Thread(s,"张三").start();
        new Thread(s,"李四").start();
        new Thread(s,"王二麻子").start();
    }
}

执行结果
张三拿到了10
王二麻子拿到了9
李四拿到了8
李四拿到了7
王二麻子拿到了6
张三拿到了5
王二麻子拿到了4
李四拿到了3
王二麻子拿到了2
张三拿到了1

 

   死锁

     产生死锁的四个必要条件:

        互斥条件:一个资源每次只能被一个进程使用。

        请求与保持条件:一个进程因为请求资源而阻塞时,对已获得的资源不放。

        不剥夺条件:进程已获得资源,在未使用完之前,不能强行剥夺。

        循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

package thread;

public class testDeadlock {
    public static void main(String[] args) {
        fangbian f = new fangbian(0,"张三");
        fangbian b = new fangbian(1,"李四");
        new Thread(f).start();
        new Thread(b).start();
    }
}

class fangbian implements Runnable{
    static wc w = new wc();
    static paper p = new paper();

    int chioce;  //顺序不同,有人选择先拿纸进wc 有人选择先进再拿纸
    String name;
    public fangbian(int chioce, String name) {
        this.chioce = chioce;
        this.name = name;
    }

    public void run() {
        if (chioce == 0) {
            synchronized (p) {
                System.out.println(name + "拿纸");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            synchronized (w) {
                System.out.println(name +"进入wc");
            }
        } else {
            synchronized (w) {
                System.out.println(name +"进入wc");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            synchronized (p) {
                System.out.println(name +"拿纸");
            }
        }

    }
}

class wc {

}

class paper {

}
运行结果:
      张三拿纸       李四进入wc       张三进入wc       李四拿纸

  lock锁

     lock 是显示的锁,需要手动开启和关闭。synchronized 是隐藏的锁,出了作用域就自动释放。

     lock只有代码块锁,synchronized 可以锁方法也可以锁代码块。

     lock具有更好性能和更高的扩展性。有很多子类。

     使用优先顺序:lock > 同步代码块(已经进入方法,分配相对应的资源)> 同步方法 (在方法之外)

package thread;

public class testDeadlock {
    public static void main(String[] args) {
        fangbian f = new fangbian(0,"张三");
        fangbian b = new fangbian(1,"李四");
        new Thread(f).start();
        new Thread(b).start();
    }
}

class fangbian implements Runnable{
    static wc w = new wc();
    static paper p = new paper();

    int chioce;
    String name;
    public fangbian(int chioce, String name) {
        this.chioce = chioce;
        this.name = name;
    }

    public void run() {
        if (chioce == 0) {
            synchronized (p) {
                System.out.println(name + "拿纸");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            synchronized (w) {
                System.out.println(name +"进入wc");
            }
        } else {
            synchronized (w) {
                System.out.println(name +"进入wc");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            synchronized (p) {
                System.out.println(name +"拿纸");
            }
        }

    }
}

class wc {

}

class paper {

}

 

  线程协作

    生产者和消费者之后互相通信。

    

 

Java多线程

原文:https://www.cnblogs.com/daylight9547/p/14649044.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!