线程

多线程

线程的创建方法

1)继承Thread类,重写run()方法

class Student extends Thread{
    public void run(){
    //run方法中的内容就是线程的内容
    }
}

在主函数中:

public static void main(String[] args) {
    Student s = new Student();//创建一个线程
    s.start()//启动线程,注意:不是s.run();
}

2)实现Runnable接口

class Student implements Runnable
//重写run方法
public void run(){
    //线程的内容
}

在主函数中:

public static void main(String[] args) {
    Student s = new Student();
    Thread thread1 = new Thread(s);//创建线程
    thread1.start();//启动线程
}

在开发中一般用第二种方法,因为java只允许但继承,而接口却可以多实现,第二种方法更加灵活。

同步代码块 关键字:synchronized

当多个线程公用一个代码块时,有时会出现一些意想不到的错误。如卖票时可能会同时卖出多张一样的票,也可能有的票没有被卖出。这就需要同步代码块。
例如:

synchronized(x){
    for(int i =0;i<100;i++){
    }
}

在这个代码块中x是一个任意的对象,被称为对象锁,当一个线程竞争到这把锁之后,在它没有执行完这些代码块之前是不会被其它线程运行的,及时抢到了cpu也没用。这就有效的防止了同步问题。
同时还可以用synchronized关键字去定义synchronized函数,这也是一种代码块,只不过它的锁是所在类的对象。

线程中的join方法

join方法是在已有的线程中加入线程,在运行完这个加入的线程之前是不会执行原有的线程的。
代码如下:
主函数:

public class Test5 {

    public static void main(String[] args) {
        Thread2 s2= new Thread2();
        Thread1 s1= new Thread1(s2);
        Thread  t1 = new Thread(s1);
        Thread  t2 = new Thread(s2);

        t1.start();             
        System.out.println("主函数结束");
    }

}

线程1:

public class Thread1 implements Runnable{
    //在一个线程中加入另一个线程的方法
    //在加入的线程没有运行完之前是不会执行当前线程的。
    private Thread t2;
    public Thread1(Thread2 t2){
        this.t2 = new Thread(t2);               
    }
    public void run(){
        System.out.println("线程一开始");

            try {
                t2.start();
                t2.join();
                //t2.join(100);等待这个线程100ms到100ms之后就会与线程2进行竞争cup.
            } catch (InterruptedException e) {

                e.printStackTrace();
            }

        System.out.println("线程1结束");


    }
}

线程2:

public class Thread2  implements Runnable{
    public void run(){

        System.out.println("线程2开始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {

            e.printStackTrace();
        }
        System.out.println("线程2结束");

    }
}

当用第二种方式产生线程时的情况:
主函数:

public class Test5 {

    public static void main(String[] args) {
        Thread2 s2= new Thread2();
        Thread1 s1= new Thread1(s2);
        Thread  t1 = new Thread(s1);
        Thread  t2 = new Thread(s2);

        t1.start();             
        System.out.println("主函数结束");
    }

}

线程1:

public class Thread1 implements Runnable{
    //在一个线程中加入另一个线程的方法
    //在加入的线程没有运行完之前是不会执行当前线程的。
    private Thread t2;
    public Thread1(Thread2 t2){
        this.t2 = new Thread(t2);               
    }
    public void run(){
        System.out.println("线程一开始");

            try {
                t2.start();
                t2.join();
                //t2.join(100);等待这个线程100ms
            } catch (InterruptedException e) {

                e.printStackTrace();
            }

        System.out.println("线程1结束");


    }
}

线程2:

public class Thread2  implements Runnable{
    public void run(){

        System.out.println("线程2开始");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {

            e.printStackTrace();
        }
        System.out.println("线程2结束");

    }
}

wait()和notify()函数。

而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备。由此可见这两个方法主要是在synchronized代码块中或者在synchronized的函数中。当两个代码块共同用同一个对象锁时经常用这两个函数。比如生产者消费者的问题:

引用其他的博客内容:

··············································································································································································································································································································
最近在学习同步的时候用到了这两个方法,开始在学习线程的时候没有注意到wait()和notify方法。原因是这两个方法不属于Thread类,它们是在lang包下面的Object类,是最底层的基础类。因此每个类的对象都可以操作这两个方法。而这两个方法的用途就是操作锁,所以它们只能在synchronized方法或者synchronized块中使用。说道wait()方法,就不得不提到Thread类中的一个静态的方法sleep(),两者间最大的区别在于:sleep()方法在睡眠的时候也一直拿着锁不放开,因此其他的线程也得不到这把锁。而wait()方法在睡眠的时候会放开锁,给其他的线程使用。wait()有两种方式获得锁:1.wait(long timeout),通过设定时间来获得锁,值得注意的是,timeout这个时间到了以后,它不会立即醒来,而是要看那个正在使用这把锁的线程是否结束。2.通过notify()的方法,通知需要这把锁的wait(),使之唤醒,而notifyAll()是通知所有的线程。
·············································································································································································································································································································
代码:

主函数:

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Product product=new Product();
        ConsumerThread consumerRun=new ConsumerThread(product);
        CreatThread creatRun=new CreatThread(product);
        Thread t1=new Thread(consumerRun);
        Thread t2=new Thread(creatRun);
        t1.start();
        t2.start();
    }
}

生产者:

public class CreatThread implements Runnable{
    private Product product;
    public CreatThread(Product product) {
        this.product=product;
    }
    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
            product.creat();
        }
    }
}

消费者:

public class ConsumerThread implements Runnable{
    private Product product;

    public ConsumerThread(Product product) {
        this.product = product;
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
            product.sumer();
        }
    }
}

生产和消费的过程:

public class Product {
    private boolean isHave = false;

    public synchronized void creat() {
        if(isHave){
            try {
                wait();
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
        }
        System.out.println("开始生产");
//      try {
//          Thread.sleep(3000);
//      } catch (InterruptedException e) {
//          e.printStackTrace();
//      }
        System.out.println("生产了一件产品");
        isHave=true;
        notify();
    }

    public synchronized void sumer() {
        System.out.println("消费前");
        if (!isHave) {
            try {
                System.out.println("等待商家生产");
                wait();
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
        }
    //  System.out.println("商家生产完成");
//      try {
//          Thread.sleep(1000);
//      } catch (InterruptedException e) {
//          
//          e.printStackTrace();
//      }
        System.out.println("消费完成");
        isHave=false;
        notify();
    }
}

sleep()方法

sleep( )方法可以使线程休眠,例如

sleep(1000)//线程休眠1秒
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值