Java多线程编程

由于可视化和分析大量线程可以从工具中受益,jcmd 除了纯文本外,还可以以 JSON 格式发出新的线程转储:

$ jcmd <pid> Thread.dump_to_file -format=json <file>

$ jcmd <pid> Thread.dump_to_file -format=json <file>

Java多线程编程_zhaoliwen是猪啊的博客-CSDN博客

Java多线程(一)实现多线程

在Java中,可以用Thread、Runnable以及Callable实现多线程

Thread 实现多线程

用Thread方法那么就是目标类继承(extends)Thread类,然后重写父类的run函数,在执行多线程程序时,使用start函数执行。

class sellTicket extends Thread{
    private int tickets = 20;
    
    @Override
    public void run() {
        try {
            this.sell();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void sell() throws InterruptedException {
        while(tickets>0)
        {
            System.out.println("卖了一张票,现在还有"+--this.tickets);
            Thread.sleep(100);
        }
    }
}


public class testThread {

    public static void main(String[] args) throws InterruptedException {
        sellTicket st = new sellTicket();
        st.start();
        int index = 0;
        while(true) {
            System.out.println("--------------");
            Thread.sleep(100);
            if(index++>30)
                break;
        }
        }
}

如果不使用多线程,那么看main函数的话,肯定是先卖票(输出卖票信息),再输出----------,但是使用了多线程以后,就是主线程main函数以及sellTicket 线程一起运行,得到了如下的结果。
在这里插入图片描述

Runnable 实现多线程

用Runnale实现多线程的方法与Thread是类似的,不同的是这个是implements Runnale,在执行多线程时是new一个Thread对象,并将Runnale的对象放入Thread对象中,再进行start()。

class sellTicket implements Runnable{
    private int tickets = 20;

    @Override
    public void run() {
        try {
            this.sell();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void sell() throws InterruptedException {
        while(tickets>0)
        {
            System.out.println("卖了一张票,现在还有"+--this.tickets);
            Thread.sleep(100);
        }
    }
}

public class testThread {
    public static void main(String[] args) throws InterruptedException {
        sellTicket st = new sellTicket();
        new Thread(st).start();
        int index = 0;
        while(true) {
            System.out.println("--------------");
            Thread.sleep(100);
            if(index++>30)
                break;
        }
	}
}

结果与上一个方法相同

Callable实现多线程

Callable实现多线程和上面两种的区别在于Callable多线程操作后可以有返回值,其次,用Callable实现的类的多线程操作写在call()函数中,具体可以看下面代码:

class TestCall implements Callable<String>
{
    @Override
    public String call() throws Exception {
        for (int i=0;i<10;i++)
        {
            System.out.println(Thread.currentThread().getName()+"   "+i);
        }
        return Thread.currentThread().getName() + "完成线程操作";
    }
}

public class testThread {
    public static void main(String[] args) throws InterruptedException, ExecutionException {

        TestCall t1 = new TestCall();
        TestCall t2 = new TestCall();
        TestCall t3 = new TestCall();
        //创建执行服务
        ExecutorService service = Executors.newFixedThreadPool(3);
        //提交执行
        Future<String> r1 = service.submit(t1);
        Future<String> r2 = service.submit(t2);
        Future<String> r3 = service.submit(t3);

        //获取结果
        String rs1 = r1.get();
        System.out.println(rs1);
        String rs2 = r2.get();
        System.out.println(rs2);
        String rs3 = r3.get();
        System.out.println(rs3);

        //关闭服务
        service.shutdownNow();
        }
}

结果如下图所示
在这里插入图片描述
Callable不能和Runnable一样直接放入Thread类执行start方法,它可以通过FutureTask来做中间媒介。

public class ConcurrentTools {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyThread thread = new MyThread();
        FutureTask futureTask = new FutureTask(thread);

        new Thread(futureTask,"A").start();
        new Thread(futureTask,"B").start();//结果会被缓存,只打印一次
        Integer i = (Integer) futureTask.get();//get会产生阻塞,最好放到最后执行
        System.out.println(i);
    }
}

class MyThread implements Callable<Integer>
{

    @Override
    public Integer call() throws Exception {
        System.out.println("call");
        return 123;
    }
}

Thread 与 Runnable 的区别和联系

  1. Runnable的实现方式是实现其接口
  2. Thread的实现方式是继承其类
  3. Thread实现了Runnable接口并进行了扩展,而Thread和Runnable的实质是实现的关系,不是同类东西,所以Runnable或Thread本身没有可比性。

初学者会有这样一个错觉:Runnable更容易可以实现多个线程间的资源共享,而Thread却不行,但实际上却不是这样的。

这是一段由Runnable方式写成的多线程代码

class sellTicket implements Runnable{

    static int tickets = 20;
    static Object o = new Object();

    @Override
    public void run() {
        try {
            this.sell();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void sell() throws InterruptedException {
            while (tickets > 0) {
                synchronized (o) {
                    if(tickets<=0)
                        break;
                    System.out.println(Thread.currentThread().getName() + "卖了一张票,现在还有" + --this.tickets);
                    Thread.sleep(100);
                }
            }

    }
}


public class testThread {


    public static void main(String[] args) throws InterruptedException, ExecutionException {
        sellTicket st1 = new sellTicket();
        sellTicket st2 = new sellTicket();
        sellTicket st3 = new sellTicket();
        new Thread(st1,"1").start();
        new Thread(st2,"2").start();
        new Thread(st3,"3").start();
        }
}

在这里插入图片描述

然后将上段代码改成Thread方式的如下

public class testThread {


    public static void main(String[] args) throws InterruptedException, ExecutionException {
        sellTicket st1 = new sellTicket();
        sellTicket st2 = new sellTicket();
        sellTicket st3 = new sellTicket();
        st1.start();
        st2.start();
        st3.start();
        }
}
class sellTicket extends Thread{

    static int tickets = 20;
    static Object o = new Object();


    @Override
    public void run() {
        try {
            this.sell();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void sell() throws InterruptedException {

            while (tickets > 0) {
                synchronized (o) {
                    if(tickets<=0)
                        break;
                    System.out.println(Thread.currentThread().getName() + "卖了一张票,现在还有" + --this.tickets);
                    Thread.sleep(100);
                }
            }
    }
}

在这里插入图片描述
由此看无论哪种方式都可以实现多个线程之间的资源共享,只需要做好同步或者锁的操作即可。

posted @ 2022-07-20 14:27  CharyGao  阅读(285)  评论(0编辑  收藏  举报