java基础-多线程

 

Java中的线程


在Java中,“线程”指两件不同的事情:
1、java.lang.Thread类的一个实例;

2、线程的执行。

java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口.(但是其实本质上都是通过Thread实现的

使用java.lang.Thread类或者java.lang.Runnable接口编写代码来定义、实例化和启动新线程。

 

一个Thread类实例只是一个对象,像Java中的任何其他对象一样,具有变量和方法,生死于堆上。

 

Java中,每个线程都有一个调用栈,即使不在程序中创建任何新的线程,线程也在后台运行着。

 

一个Java应用总是从main()方法开始运行,mian()方法运行在一个线程内,它被称为主线程。

 

一旦创建一个新的线程,就产生一个新的调用栈。

下面来看看第一种Thread方法创建

 

 

 

package Thread;

public class Threadtest extends Thread{
    @Override
    public void run(){
        System.out.println("多线程的运行代码");
        for(int i=0;i<6;i++)
        {
            System.out.println("这是多线程的逻辑代码代替实现"+i);
        }
    }
}
package Thread;

public class test {
    public static void main(String[] args) {
        Thread t0 = new Threadtest();
        t0.start();//启动
        System.out.println("---------");
        System.out.println("---------");
        System.out.println("---------");
    }
}

 

 我们发现顺序不对!

原因是main方法即主线程执行t0.start多线程后,相当于在main方法之外开启一个支流

即t0.start()为一个分割线,在它之后的代码和run方法并行运行了就像两条支流。所以没有顺序,甚至多试几次还会出现--------------在中间等情况

 

 

 

 而这就是多线程的异步性

。那么来看第二种创建方式过程(推荐)

 

 

package Thread;

public class TestRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Runnable多线程的运行代码");
        for(int i=0;i<6;i++)
        {
            System.out.println("这是Runnable多线程的逻辑代码代替实现"+i);
        }
    }
}
package Thread;

public class test {
    public static void main(String[] args) {
//        Thread t0 = new Threadtest();
//        t0.start();//启动
        Thread t2 = new Thread(new TestRunnable()); //里面有一个Runnable对象
        t2.start();
        System.out.println("---------");
        System.out.println("---------");
        System.out.println("---------");
    }
}

 

 当然Runnable不会这么简单

再来看一下加名字的变化

package Thread;

public class TestRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"Runnable多线程的运行代码");
        for(int i=0;i<6;i++)
        {
            System.out.println(Thread.currentThread().getName()+"这是Runnable多线程的逻辑代码代替实现"+i);
        }
    }
}
package Thread;

public class test {
    public static void main(String[] args) {
//        Thread t0 = new Threadtest();
//        t0.start();//启动
        Thread t2 = new Thread(new TestRunnable(),"t-2");
        t2.start();
        Thread t3 = new Thread(new TestRunnable(),"t-3");
        t3.start();
        System.out.println("---------");
        System.out.println("---------");
        System.out.println("---------");
    }
}

 

 以上两个就是创建线程的过程和方式

1继承Thread类 重写run方法

2实现Runnable接口   实现run方法(推荐)

而实现run方法也好处更多

1因为继承了Thread就不能继承其他父类,不能再继承,(java的单继承原则)

2共享资源,多线程共享一个接口实现类的对象,可以多线程处理同一个资源。比如那一个count来计数

看例子

 

 

 

 会发现count是共同的,并且还递增。

看完了上面之后再来了解一下同步与死锁的应用,思考一个问题

 

 

 

 

package ThreadTongbu;

public class test {
    public static void main(String[] args) {
        //定义一个账户
        Account a = new Account();

        User u_weixin = new User(a,2000);
        User u_zhifubao = new User(a,2000);

        Thread weixin = new Thread(u_weixin,"微信");
        Thread zhifubao = new Thread(u_zhifubao,"支付宝");
        weixin.start();
        zhifubao.start();
    }
}

class Account{
    public static int money = 3000;

    public void drawing(int m)
    {
        String name = Thread.currentThread().getName();
        if(money<m)
        {
            System.out.println(name+"操作,账户余额不足"+money);
        }
        else {
            System.out.println(name + "操作,账户原有金额" + money);
            System.out.println(name + "操作,取款金额" + m);
            money = money - m;
            System.out.println(name + "操作,取款后的金额" + money);
        }
    }
}

class  User implements Runnable{
    Account account;
    int money;
    public User(Account account,int money){
        this.account = account;
        this.money=money;
    }
    @Override
    public void run() {
        account.drawing(money);
    }
}

 

 发现钱甚至变负数了,说明线程同步的时候这样肯定不行。

所以需要线程同步与死锁

而也很简单只需要在方法上加上关键字即可

即我执行完了方法你再执行。

synchronized

 

 

 就正常了

 然后经过研究我们发现其实synchronized它锁的也可以是对象。

比如这样

 

 这样每次可以锁不不同的对象,在多线程的时候因为会共用很多代码块数据等,这样也能完美避免,只针对不同的账户,不针对什么支付宝微信或者淘宝之类。

 

 

 

 

 

 

 

 就会先支付宝再微信

posted @ 2020-05-26 18:16  To_Yang  阅读(239)  评论(0编辑  收藏  举报