[Java][华为云Java编程创造营][学习笔记][第三阶段][05_Java多线程实战][01_创建线程]

举报
John2021 发表于 2021/12/17 06:04:42 2021/12/17
【摘要】 1,创建线程 1.1,进程和线程 进程进程是并发执行程序在执行过程中资源分配和管理的基本单元。进程可以理解为一个应用程序的执行过程,应用程序一旦执行,就是一个进程。 线程线程是进程的一个执行单元,是进程内可调度实体。线程是比进程更小的独立运行的基本单位。线程也被称为轻量级进程。 通俗理解进程和线程:1,启动QQ,开了一个进程;开了迅雷,开了一个进程。在QQ的这个进程里,传输文字开了一个线程...

1,创建线程

1.1,进程和线程

进程

  • 进程是并发执行程序在执行过程中资源分配和管理的基本单元。
  • 进程可以理解为一个应用程序的执行过程,应用程序一旦执行,就是一个进程。

线程

  • 线程是进程的一个执行单元,是进程内可调度实体。
  • 线程是比进程更小的独立运行的基本单位。
  • 线程也被称为轻量级进程。

通俗理解进程和线程:

  • 1,启动QQ,开了一个进程;开了迅雷,开了一个进程。在QQ的这个进程里,传输文字开了一个线程,传输语音开了一个线程。
  • 2,通俗说:进程是爹妈,管着众多的线程子女。

进程和线程的区别

名称 进程 线程
地址空间 不同的进程之间的地址空间是独立的 同一进程的所有线程共享本进程的地址空间
资源拥有 进程之间的资源是独立的,无法共享 同一进程的所有线程共享本进程的资源
执行过程 每一个进程可以说就是一个可执行的应用程序 线程不能够独立执行,必须依存在应用程序中

1.2,创建线程的五种方式

1,继承Thread类

  • 通过继承Thread并且重写其run(),run方法中定义需要执行的任务。创建后的子类通过调用start()方法即可执行线程方法。
  • 通过继承Thread实现的线程类,多个线程间无法共享线程类的实例变量。需要创建不同Thread对象,自然不共享资源。
class UserThread extends Thread
{
    @Override
    public void run()
    {
        for (int i = 0; i < 5; i++)
        {
            System.out.println(Thread.currentThread().getName() + " is running " + i);
        }
    }
}

public class Demo1
{
    public static void main(String[] args)
    {
        for (int i = 0; i < 2; i++)
        {
            new UserThread().start();
        }
        /*
        *   Thread-1 is running 0
            Thread-1 is running 1
            Thread-1 is running 2
            Thread-1 is running 3
            Thread-1 is running 4
            Thread-0 is running 0
            Thread-0 is running 1
            Thread-0 is running 2
            Thread-0 is running 3
            Thread-0 is running 4
        * */
    }
}

2,实现Runnable接口

  • 需要先定义一个类实现Runnable接口并重写该接口的run()方法,此run方法是线程执行体。
  • 接着创建Runnable实现类的对象,作为创建Thread兑现个参数target,此Thread对象才是真正的线程对象。
  • 利用实现Runnable接口的线程类创建对象,可以实现线程之间的资源共享。
class UserRunn implements Runnable
{
    @Override
    public void run()
    {
        for (int i = 0; i < 5; i++)
        {
            System.out.println(Thread.currentThread().getName() + " is running " + i);
        }
    }
}

public class Demo2
{
    public static void main(String[] args)
    {
        UserRunn runn = new UserRunn();
        new Thread(runn).start();
        new Thread(runn).start();
        /*
        * 输出结果
        *   Thread-0 is running 0
            Thread-0 is running 1
            Thread-0 is running 2
            Thread-0 is running 3
            Thread-0 is running 4
            Thread-1 is running 0
            Thread-1 is running 1
            Thread-1 is running 2
            Thread-1 is running 3
            Thread-1 is running 4
        * */
    }
}

,3,实现Callable接口

  • 实现Callable接口实现带有返回值的线程
  • Callable接口如同Runnable接口的升级版,其提供的call()方法将作为线程的执行体,同时允许有返回值。
  • Callable对象不能直接作为Thread对象的target,因为Callable接口是Java5新增的接口,不是Runnable接口的子接口。
  • 对于这个问题的解决方案,就引入Future接口,此接口可以接受call()的返回值,RunnableFuture接口是Future接口和Runnable接口的子接口,可以作为Thread对象的target。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

class UserCallable implements Callable
{
    @Override
    public Object call() throws Exception
    {
        return "hello";
    }
}

public class Demo3
{
    public static void main(String[] args) throws ExecutionException, InterruptedException
    {
        UserCallable userCallable = new UserCallable();
        FutureTask futureTask = new FutureTask(userCallable);
        Thread t = new Thread(futureTask);
        t.start();
        System.out.println(futureTask.get());//hello
    }
}

,4,继承TimerTask

  • Timer和TimerTask可以作为实现线程的另一种方式。
  • Timer是一种线程设施,用于安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行,可以看成一个定时器,可以调度TimerTask。
  • TimerTask是一个抽象类,实现了Runnable接口,所以具备了多线程能力。
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

class UserTask extends TimerTask
{
    @Override
    public void run()
    {
        System.out.println(Thread.currentThread().getName() + " is running " + new Date());
    }
}

public class Demo4
{
    public static void main(String[] args)
    {
        Timer timer = new Timer();
        timer.schedule(new UserTask(), 2000, 3000);
        /*
        * 输出结果
        *   Timer-0 is running Wed Dec 08 15:46:39 CST 2021
            Timer-0 is running Wed Dec 08 15:46:42 CST 2021
            Timer-0 is running Wed Dec 08 15:46:45 CST 2021
            Timer-0 is running Wed Dec 08 15:46:48 CST 2021
            Timer-0 is running Wed Dec 08 15:46:51 CST 2021
            Timer-0 is running Wed Dec 08 15:46:54 CST 2021
            Timer-0 is running Wed Dec 08 15:46:57 CST 2021
            Timer-0 is running Wed Dec 08 15:47:00 CST 2021
            Timer-0 is running Wed Dec 08 15:47:03 CST 2021
            Timer-0 is running Wed Dec 08 15:47:06 CST 2021
            Timer-0 is running Wed Dec 08 15:47:09 CST 2021
            Timer-0 is running Wed Dec 08 15:47:12 CST 2021
            Timer-0 is running Wed Dec 08 15:47:15 CST 2021
            Timer-0 is running Wed Dec 08 15:47:18 CST 2021
        * */
    }
}

5,通过线程池启动多线程

  • 通过Executors的工具类可以创建线程池。
  • 提高系统响应速度,当有任务到达时,通过复用已存在的线程,无需等待新线程的创建便能立即执行。
  • 降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗。
  • 方便线程并发数的管控。因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且会造成CPU过度切换。

线程池一:FixThreadPool(int n)固定大小的线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo5
{
    public static void main(String[] args)
    {
        ExecutorService ex = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 5; i++)
        {
            ex.submit(new Runnable()
            {
                @Override
                public void run()
                {
                    for (int j = 0; j < 10; j++)
                    {
                        System.out.println(Thread.currentThread().getName() + "   " + j);
                    }
                }
            });
        }
        ex.shutdown();
        /*
        * 输出结果
        *   pool-1-thread-2   0
            pool-1-thread-2   1
            pool-1-thread-2   2
            pool-1-thread-2   3
            pool-1-thread-2   4
            pool-1-thread-2   5
            pool-1-thread-2   6
            pool-1-thread-2   7
            pool-1-thread-2   8
            pool-1-thread-2   9
            pool-1-thread-2   0
            pool-1-thread-2   1
            pool-1-thread-2   2
            pool-1-thread-2   3
            pool-1-thread-2   4
            pool-1-thread-2   5
            pool-1-thread-2   6
            pool-1-thread-2   7
            pool-1-thread-2   8
            pool-1-thread-2   9
            pool-1-thread-2   0
            pool-1-thread-2   1
            pool-1-thread-2   2
            pool-1-thread-2   3
            pool-1-thread-2   4
            pool-1-thread-2   5
            pool-1-thread-2   6
            pool-1-thread-2   7
            pool-1-thread-2   8
            pool-1-thread-2   9
            pool-1-thread-1   0
            pool-1-thread-1   1
            pool-1-thread-1   2
            pool-1-thread-1   3
            pool-1-thread-1   4
            pool-1-thread-1   5
            pool-1-thread-1   6
            pool-1-thread-1   7
            pool-1-thread-1   8
            pool-1-thread-1   9
            pool-1-thread-3   0
            pool-1-thread-3   1
            pool-1-thread-3   2
            pool-1-thread-3   3
            pool-1-thread-3   4
            pool-1-thread-3   5
            pool-1-thread-3   6
            pool-1-thread-3   7
            pool-1-thread-3   8
            pool-1-thread-3   9
        * */
    }
}

线程池二:SingleThreadPoolExecutor单线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo6
{
    public static void main(String[] args)
    {
        ExecutorService ex = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 5; i++)
        {
            ex.submit(new Runnable()
            {
                @Override
                public void run()
                {
                    for (int j = 0; j < 10; j++)
                    {
                        System.out.println(Thread.currentThread().getName() + " " + j);
                    }
                }
            });
        }
        ex.shutdown();
        /*
        * 输出结果
        *   pool-1-thread-1 0
            pool-1-thread-1 1
            pool-1-thread-1 2
            pool-1-thread-1 3
            pool-1-thread-1 4
            pool-1-thread-1 5
            pool-1-thread-1 6
            pool-1-thread-1 7
            pool-1-thread-1 8
            pool-1-thread-1 9
            pool-1-thread-1 0
            pool-1-thread-1 1
            pool-1-thread-1 2
            pool-1-thread-1 3
            pool-1-thread-1 4
            pool-1-thread-1 5
            pool-1-thread-1 6
            pool-1-thread-1 7
            pool-1-thread-1 8
            pool-1-thread-1 9
            pool-1-thread-1 0
            pool-1-thread-1 1
            pool-1-thread-1 2
            pool-1-thread-1 3
            pool-1-thread-1 4
            pool-1-thread-1 5
            pool-1-thread-1 6
            pool-1-thread-1 7
            pool-1-thread-1 8
            pool-1-thread-1 9
            pool-1-thread-1 0
            pool-1-thread-1 1
            pool-1-thread-1 2
            pool-1-thread-1 3
            pool-1-thread-1 4
            pool-1-thread-1 5
            pool-1-thread-1 6
            pool-1-thread-1 7
            pool-1-thread-1 8
            pool-1-thread-1 9
            pool-1-thread-1 0
            pool-1-thread-1 1
            pool-1-thread-1 2
            pool-1-thread-1 3
            pool-1-thread-1 4
            pool-1-thread-1 5
            pool-1-thread-1 6
            pool-1-thread-1 7
            pool-1-thread-1 8
            pool-1-thread-1 9
        * */
    }
}

线程池三:CashedThreadPool()缓存线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo7
{
    public static void main(String[] args)
    {
        ExecutorService ex = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++)
        {
            ex.submit(new Runnable()
            {
                @Override
                public void run()
                {
                    for (int j = 0; j < 10; j++)
                    {
                        System.out.println(Thread.currentThread().getName() + " " + j);
                    }
                }
            });
        }
        ex.shutdown();
        /*
        * 输出结果
        *   pool-1-thread-1 0
            pool-1-thread-2 0
            pool-1-thread-2 1
            pool-1-thread-2 2
            pool-1-thread-4 0
            pool-1-thread-4 1
            pool-1-thread-4 2
            pool-1-thread-4 3
            pool-1-thread-4 4
            pool-1-thread-4 5
            pool-1-thread-4 6
            pool-1-thread-4 7
            pool-1-thread-4 8
            pool-1-thread-4 9
            pool-1-thread-1 1
            pool-1-thread-1 2
            pool-1-thread-1 3
            pool-1-thread-1 4
            pool-1-thread-1 5
            pool-1-thread-1 6
            pool-1-thread-1 7
            pool-1-thread-1 8
            pool-1-thread-1 9
            pool-1-thread-3 0
            pool-1-thread-5 0
            pool-1-thread-2 3
            pool-1-thread-2 4
            pool-1-thread-2 5
            pool-1-thread-2 6
            pool-1-thread-5 1
            pool-1-thread-3 1
            pool-1-thread-3 2
            pool-1-thread-3 3
            pool-1-thread-5 2
            pool-1-thread-5 3
            pool-1-thread-5 4
            pool-1-thread-5 5
            pool-1-thread-5 6
            pool-1-thread-5 7
            pool-1-thread-5 8
            pool-1-thread-5 9
            pool-1-thread-2 7
            pool-1-thread-3 4
            pool-1-thread-3 5
            pool-1-thread-3 6
            pool-1-thread-3 7
            pool-1-thread-3 8
            pool-1-thread-3 9
            pool-1-thread-2 8
            pool-1-thread-2 9
        * */
    }
}

线程池四:newScheduledThreadPool()创建一个周期性的线程池,支持定时及周期性执行任务

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Demo8
{
    public static void main(String[] args)
    {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        scheduledThreadPool.scheduleAtFixedRate(new Runnable()
        {
            @Override
            public void run()
            {
                System.out.println(Thread.currentThread().getName() + ",执行 " + new Date());
            }
        }, 1, 3, TimeUnit.SECONDS);
        /*
        * 输出结果:
        *   pool-1-thread-1,执行 Tue Dec 14 11:35:55 CST 2021
            pool-1-thread-1,执行 Tue Dec 14 11:35:58 CST 2021
            pool-1-thread-2,执行 Tue Dec 14 11:36:01 CST 2021
            pool-1-thread-1,执行 Tue Dec 14 11:36:04 CST 2021
            pool-1-thread-3,执行 Tue Dec 14 11:36:07 CST 2021
            pool-1-thread-3,执行 Tue Dec 14 11:36:10 CST 2021
            pool-1-thread-4,执行 Tue Dec 14 11:36:13 CST 2021
            pool-1-thread-4,执行 Tue Dec 14 11:36:16 CST 2021
        * */
    }
}

线程池五:newWorkStealingPool新的线程池类ForkJoinPool的扩展

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo9
{
    public static void main(String[] args) throws InterruptedException
    {
        System.out.println("---start---");
        ExecutorService executorService = Executors.newWorkStealingPool();
        for (int i = 0; i < 10; i++)
        {
            executorService.submit(new Runnable()
            {
                @Override
                public void run()
                {
                    System.out.println(Thread.currentThread().getName());
                }
            });
        }
        Thread.sleep(3000);//让主线程等待子线程执行完毕,也可以使用计数器方式
        System.out.println("---end---");
        /*
        * 输出结果
        *   ---start---
            ForkJoinPool-1-worker-1
            ForkJoinPool-1-worker-1
            ForkJoinPool-1-worker-1
            ForkJoinPool-1-worker-1
            ForkJoinPool-1-worker-1
            ForkJoinPool-1-worker-1
            ForkJoinPool-1-worker-1
            ForkJoinPool-1-worker-1
            ForkJoinPool-1-worker-1
            ForkJoinPool-1-worker-1
            ---end---
        * */
    }
}

1.3,Thread类和Runnable接口区别

继承Thread类实现卖票操作

class MyThread extends Thread
{
    private int ticket = 10;
    private String name;

    public MyThread(String name)
    {
        this.name = name;
    }

    public void run()
    {
        for (int i = 0; i < 500; i++)
        {
            if (this.ticket > 0)
            {
                System.out.println(this.name + "卖出第" + (10 - this.ticket-- + 1) + "票");
            }
        }
    }
}

public class Demo10
{
    public static void main(String[] args)
    {
        MyThread mt1 = new MyThread("一号窗口");
        MyThread mt2 = new MyThread("二号窗口");
        MyThread mt3 = new MyThread("三号窗口");
        mt1.start();
        mt2.start();
        mt3.start();
    }
    /*
    * 输出结果
    *   一号窗口卖出第1票
        三号窗口卖出第1票
        三号窗口卖出第2票
        三号窗口卖出第3票
        三号窗口卖出第4票
        三号窗口卖出第5票
        三号窗口卖出第6票
        三号窗口卖出第7票
        三号窗口卖出第8票
        三号窗口卖出第9票
        三号窗口卖出第10票
        二号窗口卖出第1票
        二号窗口卖出第2票
        二号窗口卖出第3票
        一号窗口卖出第2票
        二号窗口卖出第4票
        二号窗口卖出第5票
        二号窗口卖出第6票
        二号窗口卖出第7票
        二号窗口卖出第8票
        二号窗口卖出第9票
        二号窗口卖出第10票
        一号窗口卖出第3票
        一号窗口卖出第4票
        一号窗口卖出第5票
        一号窗口卖出第6票
        一号窗口卖出第7票
        一号窗口卖出第8票
        一号窗口卖出第9票
        一号窗口卖出第10票
    * */
}

实现Runnable接口实现卖票操作

class MyThread implements Runnable
{
    private int ticket = 10;

    @Override
    public void run()
    {
        for (int i = 0; i < 500; i++)
        {
            if (this.ticket > 0)
            {
                System.out.println(Thread.currentThread().getName() + "卖出第" + (10 - this.ticket-- + 1) + "票");
            }
        }
    }
}

public class Demo11
{
    public static void main(String[] args)
    {
        MyThread mt = new MyThread();
        Thread t1 = new Thread(mt, "一号窗口");
        Thread t2 = new Thread(mt, "二号窗口");
        Thread t3 = new Thread(mt, "三号窗口");
        t1.start();
        t2.start();
        t3.start();
    }
}
/*
* 输出结果
*   一号窗口卖出第1票
    一号窗口卖出第4票
    一号窗口卖出第5票
    一号窗口卖出第6票
    一号窗口卖出第7票
    一号窗口卖出第8票
    一号窗口卖出第9票
    一号窗口卖出第10票
    三号窗口卖出第3票
    二号窗口卖出第2票
* */

1.4,线程start和run方法的区别

线程对象调用run方法案例

class UserThread extends Thread
{
    public void run()
    {
        System.out.println(Thread.currentThread().getName() + ",执行run方法");
    }
}

public class Demo12
{
    public static void main(String[] args)
    {
        System.out.println(Thread.currentThread().getName() + ",执行main方法");
        UserThread userThread = new UserThread();
        userThread.run();
        /*
        * 输出结果
        *   main,执行main方法
            main,执行run方法
        * */
    }
}

线程对象使用start()方法案例

class UserThread extends Thread
{
    public void run()
    {
        System.out.println(Thread.currentThread().getName() + ",执行run方法");
    }
}

public class Demo13
{
    public static void main(String[] args)
    {
        System.out.println(Thread.currentThread().getName() + ",执行main方法");
        UserThread userThread = new UserThread();
        userThread.start();
        /*
        * 输出结果
        *   main,执行main方法
            Thread-0,执行run方法
        * */
    }
}

1.5,线程的优先级

  • Java线程的优先级范围是1-10,默认优先级是5,10最高。
  • 线程的优先级仍然无法保障线程的执行次序。
  • 优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。
  • 主线程main的优先级是5.

Java线程的优先级案例

class UserThread extends Thread
{
    public void run()
    {
        for (int i = 0; i < 10; i++)
        {
            System.out.println(Thread.currentThread().getName() + "第" + i + "次执行!");
            try
            {
                Thread.sleep(100);
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}

class UserRunn implements Runnable
{
    @Override
    public void run()
    {
        for (int i = 0; i < 10; i++)
        {
            System.out.println(Thread.currentThread().getName() + ",第" + i + "次执行!");
            try
            {
                Thread.sleep(100);
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}

public class Demo14
{
    public static void main(String[] args)
    {
        Thread t1 = new UserThread();
        Thread t2 = new Thread(new UserRunn());
        //t1.setPriority(10);
        t2.setPriority(1);
        t2.start();
        //t1.start();
        /*
        * t1执行结果
        *   Thread-0第0次执行!
            Thread-0第1次执行!
            Thread-0第2次执行!
            Thread-0第3次执行!
            Thread-0第4次执行!
            Thread-0第5次执行!
            Thread-0第6次执行!
            Thread-0第7次执行!
            Thread-0第8次执行!
            Thread-0第9次执行!
        * */
        /*
        * t2执行结果
        *   Thread-1,第0次执行!
            Thread-1,第1次执行!
            Thread-1,第2次执行!
            Thread-1,第3次执行!
            Thread-1,第4次执行!
            Thread-1,第5次执行!
            Thread-1,第6次执行!
            Thread-1,第7次执行!
            Thread-1,第8次执行!
            Thread-1,第9次执行!
        * */
    }
}

1.6,定时线程的任务调度

定时线程Schedule():延时不追加执行任务

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

class UserTask extends TimerTask
{
    @Override
    public void run()
    {
        System.out.println(Thread.currentThread().getName() + "," + new Date());
    }
}

public class Demo15
{
    public static void main(String[] args)
    {
        Timer t = new Timer();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date date = null;
        try
        {
            date = sdf.parse("2021-12-14 00:00:00");
        } catch (ParseException e)
        {
            e.printStackTrace();
        }
        t.schedule(new UserTask(), date, 3 * 60 * 1000);
        /*
         * 输出结果
         * Timer-0,Tue Dec 14 21:48:23 CST 2021
         * */
    }
}

定时线程scheduleAtFixedRate():延时追加执行任务

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

class UserTask extends TimerTask
{
    @Override
    public void run()
    {
        System.out.println(Thread.currentThread().getName() + "," + new Date());
    }
}

public class Demo16
{
    public static void main(String[] args)
    {
        Timer t = new Timer();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date date = null;
        try
        {
            date = sdf.parse("2021-12-14 05:00:00");
        } catch (ParseException e)
        {
            e.printStackTrace();
        }
        t.scheduleAtFixedRate(new UserTask(), date, 3 * 60 * 1000);
        /*
        * 输出结果
        *   Timer-0,Tue Dec 14 21:40:32 CST 2021
            Timer-0,Tue Dec 14 21:40:32 CST 2021
        * */
    }
}

1.7,接口同步回调和异步回调

  • 同步调用

    • 一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用。
  • 回调

    • 一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口。
  • 异步调用

    • 一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方。
  • 接口同步回调案例

interface Callback
{
    public void process(int status);
}

class MyCallback implements Callback
{
    @Override
    public void process(int status)
    {
        System.out.println("处理成功,返回状态为:" + status);
    }
}

class Server
{
    public void getMsg(Callback callback, String msg) throws InterruptedException
    {
        System.out.println("服务端获得消息:" + msg);
        //模拟处理消息过程,等待两秒
        Thread.sleep(2000);
        System.out.println("服务端处理成功,返回状态为200");
        //处理完消息,调用回调方法,告知客户端
        callback.process(200);
    }
}

class Client
{
    Server server;

    public Client(Server server)
    {
        this.server = server;
    }

    public void sendMsg(final String msg)
    {
        System.out.println("客户端正在发送消息:" + msg);
        try
        {
            server.getMsg(new MyCallback(), msg);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        System.out.println("客户端已经发送消息给服务器了,请稍等");
    }
}

/*
 * 接口同步回调案例
 * */
public class Demo17
{
    public static void main(String[] args)
    {
        Server server = new Server();
        Client client = new Client(server);
        client.sendMsg("我要充值");
        /*
        * 输出结果
        *   客户端正在发送消息:我要充值
            服务端获得消息:我要充值
            服务端处理成功,返回状态为200
            处理成功,返回状态为:200
            客户端已经发送消息给服务器了,请稍等
        * */
    }
}
  • 接口异步调用案例
interface Callback
{
    public void process(int status);
}

class MyCallback implements Callback
{
    @Override
    public void process(int status)
    {
        System.out.println("处理成功,返回状态为:" + status);
    }
}

class Server
{
    public void getMsg(Callback callback, String msg) throws InterruptedException
    {
        System.out.println("服务端获得消息:" + msg);
        //模拟处理消息过程,等待两秒
        Thread.sleep(2000);
        System.out.println("服务端处理成功,返回状态为200");
        //处理完消息,调用回调方法,告知客户端
        callback.process(200);
    }
}

class Client
{
    Server server;

    public Client(Server server)
    {
        this.server = server;
    }

    public void sendMsg(final String msg)
    {
        System.out.println("客户端正在发送消息:" + msg);
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    //调用server类的获取消息方法,并且传入mycallback对象
                    server.getMsg(new MyCallback(), msg);
                } catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }).start();
        System.out.println("客户端已经发送消息给服务器了,请稍等");
    }
}

public class Demo18
{
    public static void main(String[] args)
    {
        Server server = new Server();
        Client client = new Client(server);
        client.sendMsg("我要充值");
        /*
        * 输出结果
        *   客户端正在发送消息:我要充值
            客户端已经发送消息给服务器了,请稍等
            服务端获得消息:我要充值
            服务端处理成功,返回状态为200
            处理成功,返回状态为:200
        * */
    }
}
  • 回调分为同步和异步,区别就是需不需要等待服务器端的返回结果
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。