Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

In Java, you can implement multithreading with Threads, Runnable, and Callable

Thread implementation multithreading

Using the Thread method extends the Thread class and then overrides the run function of the parent class, using the start function when executing a multithreaded program.

class sellTicket extends Thread{
    private int tickets = 20;
    
    @Override
    public void run(a) {
        try {
            this.sell();
        } catch(InterruptedException e) { e.printStackTrace(); }}public void sell(a) throws InterruptedException {
        while(tickets>0)
        {
            System.out.println("Sold a ticket and still has one."+--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; }}}Copy the code

Without multithreading, the main function would have sold tickets first and then ———-, but with multithreading, the main function and the sellTicket thread run together, resulting in the following result.

Runnable implements multithreading

Multithreading with Runnale is implemented in a similar way to Thread, except that it implements Runnale, new a Thread object, puts the Runnale object into the Thread object, and then starts ().

class sellTicket implements Runnable{
    private int tickets = 20;

    @Override
    public void run(a) {
        try {
            this.sell();
        } catch(InterruptedException e) { e.printStackTrace(); }}public void sell(a) throws InterruptedException {
        while(tickets>0)
        {
            System.out.println("Sold a ticket and still has one."+--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; }}}Copy the code

The result is the same as the previous method

Callable implements multithreading

The call() function is used to perform multithreaded operations on a Callable class. The call() function is used to perform multithreaded operations on a Callable class.

class TestCall implements Callable<String>
{
    @Override
    public String call(a) throws Exception {
        for (int i=0; i<10; i++) { System.out.println(Thread.currentThread().getName()+""+i);
        }
        return Thread.currentThread().getName() + "Finish thread operation"; }}public class testThread {
    public static void main(String[] args) throws InterruptedException, ExecutionException {

        TestCall t1 = new TestCall();
        TestCall t2 = new TestCall();
        TestCall t3 = new TestCall();
        // Create the execution service
        ExecutorService service = Executors.newFixedThreadPool(3);
        // Commit execution
        Future<String> r1 = service.submit(t1);
        Future<String> r2 = service.submit(t2);
        Future<String> r3 = service.submit(t3);

        // Get the result
        String rs1 = r1.get();
        System.out.println(rs1);
        String rs2 = r2.get();
        System.out.println(rs2);
        String rs3 = r3.get();
        System.out.println(rs3);

        // Shut down the serviceservice.shutdownNow(); }}Copy the code

The result is shown below

Unlike Runnable, Callable cannot be placed directly into the Thread class to execute the start method. It can be mediated by 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();// The results are cached and printed only once
        Integer i = (Integer) futureTask.get();// Get blocks and is best done lastSystem.out.println(i); }}class MyThread implements Callable<Integer>
{

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

The difference between Thread and Runnable

  1. Runnable is implemented by implementing its interface
  2. Threads are implemented by inheriting their classes
  3. Thread implements the Runnable interface and extends it. In essence, Thread and Runnable are implementation relations, not homogeneous things, so there is no comparison between Runnable and Thread.

Beginners may have the illusion that Runnable makes it easier to share resources between threads than threads, but this is not the case.

This is a piece of multithreaded code written in Runnable mode

class sellTicket implements Runnable{

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

    @Override
    public void run(a) {
        try {
            this.sell();
        } catch(InterruptedException e) { e.printStackTrace(); }}public void sell(a) throws InterruptedException {
            while (tickets > 0) {
                synchronized (o) {
                    if(tickets<=0)
                        break;
                    System.out.println(Thread.currentThread().getName() + "Sold a ticket and still has one." + --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(); }}Copy the code

Then change the previous code to Thread as follows

public class testThread {


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

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


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

            while (tickets > 0) {
                synchronized (o) {
                    if(tickets<=0)
                        break;
                    System.out.println(Thread.currentThread().getName() + "Sold a ticket and still has one." + --this.tickets);
                    Thread.sleep(100); }}}}Copy the code

Therefore, no matter which way can realize the resource sharing between multiple threads, just need to do a good synchronization or lock operation.