java多线程编程

线程基本概念java

进程:内存中正在进行的一个程序多线程

线程:进程中的一个执行流程并发

多线程:有两个 或者 两个以上并发的执行流程ide

线程的生命周期,线程分为如下五种状态this

  • (新建) New Thread();
  • (就绪) start();
  • (运行) run();
  • (阻塞) 暂停执行spa

    • sleep(就像咱们作总结睡着了),join(让其余人先作,就像作总结时中间让其余人讲话)阻塞

      sleep:等待多少毫秒;超过了以后回复就绪状态等待cpu调用执行
      join:等待其余线程执行完,线程A调用了线程B的join();方法,那么线程A等线程B执行完再执行线程

    • 同步(排队)
    • wait(晕过去了)
  • (死亡)

线程图解:对象

主线程blog

当Java程序启动时,一个线程马上运行,该线程通 常叫作程序的主线程(main thread),==它是程序 开始时就执行的==。继承

主方法就是主线程的任务 main();

public class TestThreadMain {

    public static void main(String[] args) {

        // 得到当前的线程                      主线程名字,优先级,主线程组

        System.out.println(Thread.currentThread());//Thread[main,5,main]

        System.out.println(Thread.currentThread().getName());//main

    }

}

问题:启动一个java应用程序至少启动几个主线程?

会先启动两个线程:一个主线程,一个垃圾回收线程

子线程

默认的名字:Thread —— 数字

建立子线程

  • 方式一:继承自Thread类
  • 方式二:实现Runnable 接口

区别:
1. 继承Thread类,继承了Thread类的全部能够继承的;Runnable接口,只有run();
2. Runnable接口有利于资源共享

但愿主线程最后结束

  • sleep() 暂停多长时间
  • isAlive() 判断线程仍在运行,isAlive()方法返回true,若是丌是则 返回false。
  • join() 等待一个线程执行完

/** 建立子线程示例代码 */

//建立子线程方法一:继承自Thread类  
class MyThread extends Thread{
    MyThread(String name){
        super(name);
    }

    //子线程的任务功能在run中
    @Override
    public void run() {
        for(int i = 1; i<= 3 ; i++){
            System.out.println(Thread.currentThread().getName() +":"+i);
        }
    }

}

//建立子线程方法二:实现Runnable 接口    用的较多,有利于资源共享
class ThreadDemo implements Runnable{

    @Override
    public void run() {
        for(int i = 1; i<= 3 ; i++){
            System.out.println(Thread.currentThread().getName() +"吃饭");
        }

    }
}

public class TestThread1 {

    public static void main(String[] args) {
//      //建立一个线程对象
//      Thread t = new Thread();
//      //启动线程
//      t.start();

//      //建立一个子线程
//      MyThread t1 = new MyThread("t1");//新建
//      //启动子线程,必须用start,而且只能启动一次
//      t1.start();//就绪

        //不是线程对象
        ThreadDemo demo = new ThreadDemo();
        //                     绑定ThreadDemo类对象
        //Thread zhangsan = new Thread(demo);
        Thread zhangsan = new Thread(demo,"张三");
        Thread lisi = new Thread(demo,"李四");

        //设置优先级
        /*  lisi.setPriority(10);
        zhangsan.setPriority(1);*/
        //最低,普通,最高        比直接赋予数字好一些
        //1   5   10
        zhangsan.setPriority(Thread.MAX_PRIORITY);
        zhangsan.setPriority(Thread.MIN_PRIORITY);
        zhangsan.setPriority(Thread.NORM_PRIORITY);

        //启动线程
        zhangsan.start();
        lisi.start();

        //但愿主线程最后结束方法一
    /*  try {
            Thread.sleep(1000);//等1000毫秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        ////但愿主线程最后结束方法二:判断子线程是否运行
/*      if(zhangsan.isAlive() || lisi.isAlive()){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }*/

    //但愿主线程最后结束方法三:让子线程都执行完才能恢复主线程
        try {
            zhangsan.join();
            lisi.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("主线程结束");

    }

}
线程优先级

1 – 10

10最高

  • 理论上,优先级高的线程比优先级低的线程得到更 多的CPU时间
  • 实际上,线程得到的CPU时间一般由包括优先级在 内的==多个因素==决定
  • 理论上,等优先级线程有同等的权利使用CPU

/** 建立子线程 */

//建立子线程方法一:继承自Thread类  
class MyThread extends Thread{
    MyThread(String name){
        super(name);
    }

    //子线程的任务功能在run中
    @Override
    public void run() {
        for(int i = 1; i<= 3 ; i++){
            System.out.println(Thread.currentThread().getName() +":"+i);
        }
    }

}

//建立子线程方法二:实现Runnable 接口    用的较多,有利于资源共享
class ThreadDemo implements Runnable{

    @Override
    public void run() {
        for(int i = 1; i<= 3 ; i++){
            System.out.println(Thread.currentThread().getName() +"吃饭");
        }

    }
}

public class TestThread1 {

    public static void main(String[] args) {
//      //建立一个线程对象
//      Thread t = new Thread();
//      //启动线程
//      t.start();

//      //建立一个子线程
//      MyThread t1 = new MyThread("t1");//新建
//      //启动子线程,必须用start,而且只能启动一次
//      t1.start();//就绪

        //不是线程对象
        ThreadDemo demo = new ThreadDemo();
        //                     绑定ThreadDemo类对象
        //Thread zhangsan = new Thread(demo);
        Thread zhangsan = new Thread(demo,"张三");
        Thread lisi = new Thread(demo,"李四");

        //设置优先级
        /*  lisi.setPriority(10);
        zhangsan.setPriority(1);*/
        //最低,普通,最高        比直接赋予数字好一些
        //1   5   10
        zhangsan.setPriority(Thread.MAX_PRIORITY);
        zhangsan.setPriority(Thread.MIN_PRIORITY);
        zhangsan.setPriority(Thread.NORM_PRIORITY);

        //启动线程
        zhangsan.start();
        lisi.start();

        //但愿主线程最后结束方法一
    /*  try {
            Thread.sleep(1000);//等1000毫秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        ////但愿主线程最后结束方法二:判断子线程是否运行
/*      if(zhangsan.isAlive() || lisi.isAlive()){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }*/

    ////但愿主线程最后结束方法三:让子线程都执行完才能恢复主线程
        try {
            zhangsan.join();
            lisi.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("主线程结束");

    }

}
线程其它方法interrupt()线程中断 :sleep()和join()

**问题:**java线程何时会引起InterruptedException ?

前提:当前线程处于sleep或者join时,被其余线程中断了,那么当前线程会进行异常处理

class ThreadDemo1 implements Runnable{

    @Override

    public void run() {

        for(int i = 1 ; i <=5 ; i++){

            System.out.println(Thread.currentThread().getName()+","+i);

            if(i == 3){

                try {

                    //Thread.sleep(1000);

                    Thread.currentThread().join();

                } catch (InterruptedException e) {

                    System.out.println("进入异常处理了");

                //  e.printStackTrace();

                }

            }

        }

    }

}

public class TestThreadInterrupt {

    public static void main(String[] args) {

        ThreadDemo1 demo1 = new ThreadDemo1();

        Thread t1 = new Thread(demo1);

        t1.start();

        //主线程调用了子线程t1的interrupt方法,子线程t1被中断进入异常处理

        t1.interrupt();

    }

}

yield() 线程让步 (了解便可,如今基本不用):

Thread.yield():不能彻底保证线程让步

class ThreadDemo1 implements Runnable{

    @Override

    public void run() {

        for(int i = 1 ; i <=5 ; i++){

            System.out.println(Thread.currentThread().getName()+","+i);

            if(i == 3){

                try {

                    //Thread.sleep(1000);

                    Thread.currentThread().join();

                } catch (InterruptedException e) {

                    System.out.println("进入异常处理了");

                //  e.printStackTrace();

                }

            }

        }

    }

}

public class TestThreadInterrupt {

    public static void main(String[] args) {

        ThreadDemo1 demo1 = new ThreadDemo1();

        Thread t1 = new Thread(demo1);

        t1.start();

        //主线程调用了子线程t1的iterrupt方法,子线程t1被中断进入异常处理

        t1.interrupt();

    }

}

线程的同步什么是同步

某一时刻 此资源 只能被一个线程独占。
线程同步的真实意思和字面意思刚好相反。线程同步的真实意思,实际上是“排队”:几个线程之间要排队,一个一个对共享资源进行操做,而不是同时进行操做。

为何使用同步

当两个或两个以上的线程须要共享资源,他们须要某种方法来肯定资源在某一时刻仅被一个线程占用,达到此目的的过程叫作同步。(某一时刻资源只能被一个线程独占)

使用同步

  • 同步代码块
    咱们能够将对某个方法的调用放入一个synchronized块内

synchronized(对象){

同步块;

}

同步方法,锁的是对象 this
synchronized  方法{   }
1
/**同步示例代码*/
class Bank implements Runnable{
    int money = 0;
    //存钱
    //同步方法
    synchronized public void setMoney(){
        money += 100;//存100
        System.out.println(Thread.currentThread().getName() + "存了100,余额:" +money);
    }
    @Override
    public void run() {
        for(int i = 0 ; i < 3 ; i++){
            //同步锁
            //同步块
/*          synchronized(this){
            setMoney();
            }*/
            setMoney();
        }

    }

}
public class TestBank {

    public static void main(String[] args) {
        Bank bank = new Bank();
        Thread zhangsan = new Thread(bank,"zhangsan");
        Thread lisi = new Thread(bank,"lisi");
        zhangsan.start();
        lisi.start();
    }

}
Lock优点

能够显示加锁,释放锁

得到锁:

当一个线程 访问此对象的 同步块 或 同步方法的时候,
申请同步锁,申请成功了,就得到了锁。在执行 同步块
和 同步方法的过程当中,其它线程 进入 线程锁定池中处于
阻塞状态。只有 当前执行锁的线程 释放了锁 其它线程
才有 机会 得到CPU的调用执行。

释放锁:

1.同步方法或同步块中的 代码正常执行完了,就释放了;
2. 出现了未处理的 异常Exception和
Error时 ,释放锁;
3。 break,return语句,会结束方法或
代码块,那么会释放锁。
4. 执行了 wait()会释放锁。

语法:
try{  
    加锁lock

}finally{   
    释放unLock

}

lock做用

能够显示加锁和释放锁
提供了更多功能
死锁

每一个对象只有一个锁(lock)不之相关联
实现同步是要很大的系统开销做为代价的,甚至可 能形成死锁,因此尽可能避免无谓的同步控制
/**死锁示例代码 */
class Zhangsan{
    public void say(){
        System.out.println("你给我书,我就给你画");
    }
    public void get(){
        System.out.println("张三得到了书");
    }
}

class Lisi{
    public void say(){
        System.out.println("你给我画,我就给你书");
    }
    public void get(){
        System.out.println("李四得到了画");
    }
}
class LockDemo implements Runnable{
    static Zhangsan zhangsan = new Zhangsan();
    static Lisi lisi = new Lisi();
    boolean tag ;

    @Override
    public void run() {
        if(tag == true){//张三
            synchronized(zhangsan){
            zhangsan.say();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            synchronized(lisi){
                zhangsan.get();
            }
            }
        }else{//李四
            synchronized(lisi){
                lisi.say();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                synchronized(zhangsan){
                    lisi.get();
                }
            }
        }

    }

}
public class Testlock {

    public static void main(String[] args) {
        LockDemo demo1 = new LockDemo();
        demo1.tag = true;
        LockDemo demo2 = new LockDemo();
        demo2.tag = false;
        Thread t1 = new Thread(demo1);
        Thread t2 = new Thread(demo2);
        t1.start();
        t2.start();
    }

}

wait()和sleep的区别:

区别:
时间参数
wait()能够可定时间也能够丌指定; sleep()必须指定时间;
同步状态
sleep()释放执行权,不释放锁 ;wait释放执行权,释放锁
class Show implements Runnable{
    int i = 10 ;
    @Override
    synchronized public void run() {
        for(; i >= 0 ; i--){

            if(i == 5  && Thread.currentThread().getName().equals("t1:")){
                try {
                    //Thread.sleep(100000);
                    wait(1000);
                    System.out.println("我醒了");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+i);
        }   

    }

}

public class Exercise1 {

    public static void main(String[] args) {
        Show sh = new Show();
        Thread t1 = new Thread(sh,"t1:");
        Thread t2 = new Thread(sh,"t2:");
        t1.start();
        t2.start();

    }

}
包子铺实例理解wait()、notify()

package day26;
class QingFeng {
    private int count;//包子数量
    private boolean tag = false;//true ->有包子,false->没包子

    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }

    //生产包子
    synchronized public void put(int count){
        //有包子,休息
        if(tag == true){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //没有包子 false
        this.count = count;
        System.out.println("生产了" +this.count);
        tag = true;
        notify();//唤醒销售
    }
    //销售包子
    synchronized public void get(){
        //没包子可卖,休息一会
        if(tag == false){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 有包子true
        System.out.println("卖了" +this.count);
        tag = false;//卖完了
        notify();//唤醒厨师
    }

}
//生产
class Producer implements Runnable{
    QingFeng qingfeng;

    public Producer(QingFeng qingfeng) {
        super();
        this.qingfeng = qingfeng;
    }

    public Producer() {
        super();
    }

    @Override
    public void run() {
        //生产
        for(int i = 1 ; i <=5 ; i++){
            qingfeng.put(i);
        }
    }

}

//销售
class Consumer implements Runnable{
    QingFeng qingfeng;

    public Consumer() {
        super();
    }

    public Consumer(QingFeng qingfeng) {
        super();
        this.qingfeng = qingfeng;
    }

    @Override
    public void run() {
        for(int i = 1 ; i <= 5 ; i++){
            qingfeng.get();
        }
    }

}

public class Exercise2 {

    public static void main(String[] args) {
        QingFeng qingfeng = new QingFeng();
        Producer pro = new Producer(qingfeng);
        Consumer con = new Consumer(qingfeng) ;
        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(con);
        t1.start();
        t2.start();

    }

}

相关文章
相关标签/搜索