Java 实现线程的三种方式

Java 实现线程的三种方式

说明: Java 不支持多继承, 所以继承了 Thread 类就无法继承其它类, 但是可以实现多个接口.

1. 继承 Thread 类, 重写 run 方法
public class ThreadDemo {
  @Test
  public void testThread() {
    new MyThread().start();
    
    try {
      Thread.sleep(1000);
    }catch (Exception e) {
      e.printStackTrace();
    }
  }
}


class MyThread extends Thread {
  @Override
  public void run() {
    for (int i = 0; i < 10; i++) {
      System.out.println("===> 线程: " + Thread.currentThread().getName() + " - " + i);
    }
  }
}
2. 实现 Runnable 接口, 重写 run 方法
public class RunnableDemo {
  @Test
  public void testRunnable() {
    Thread thread = new Thread(new MyRunnable());
    thread.start();

    try {
      Thread.sleep(1000);
    }catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}


class MyRunnable implements Runnable {
  @Override
  public void run() {
    for (int i = 0; i < 10; i++) {
      System.out.println("===> 线程: " + Thread.currentThread().getName() + " - " + i);
    }
  }
}
3. 实现 Callable 接口, 重写 call 方法
public class CallableDemo {
  @Test
  public void testCallable() throws Exception{
    FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
    Thread thread = new Thread(futureTask);
    thread.start();

    System.out.println("===> 获取线程执行结果: " + futureTask.get());

    try {
      Thread.sleep(1000);
    }catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

class MyCallable implements Callable<String> {
  @Override
  public String call() throws Exception {
    for (int i = 0; i < 10; i++) {
      System.out.println("===> 线程: " + Thread.currentThread().getName() + " - " + i);
    }
    return "线程执行完毕";
  }
}

Java 为什么会产生多线程安全问题 ?

Java中的线程安全问题‌是指当多个线程同时访问和操作同一数据时,由于线程调度的非确定性,可能导致数据的不一致和错误.

多线程问题例子 - 卖票:

public class BuyTicketsMultiThreads {

  private static int tickets = 30;	// 多个线程访问操作修改的相同的资源

  public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
      new Thread(() -> {
        while (true) {
          if (tickets > 0) {
            System.out.println("===> 售票员: " + Thread.currentThread().getName() + ", 售出票号为: " + tickets);
            tickets--;	// 多线程问题, 因为这里的操作不是原子性
          } else {
            break;
          }
        }
      }).start();
    }
  }
}

/*
===> 售票员: Thread-0, 售出票号为: 30
===> 售票员: Thread-0, 售出票号为: 29
===> 售票员: Thread-0, 售出票号为: 28
===> 售票员: Thread-0, 售出票号为: 27
===> 售票员: Thread-6, 售出票号为: 30
===> 售票员: Thread-9, 售出票号为: 30
===> 售票员: Thread-7, 售出票号为: 30
===> 售票员: Thread-8, 售出票号为: 30
===> 售票员: Thread-4, 售出票号为: 30
===> 售票员: Thread-2, 售出票号为: 30
===> 售票员: Thread-0, 售出票号为: 26
===> 售票员: Thread-6, 售出票号为: 25
===> 售票员: Thread-5, 售出票号为: 30
===> 售票员: Thread-1, 售出票号为: 30
===> 售票员: Thread-3, 售出票号为: 30
===> 售票员: Thread-9, 售出票号为: 24
===> 售票员: Thread-7, 售出票号为: 23
===> 售票员: Thread-7, 售出票号为: 13
===> 售票员: Thread-8, 售出票号为: 22
===> 售票员: Thread-4, 售出票号为: 21
===> 售票员: Thread-2, 售出票号为: 20
===> 售票员: Thread-0, 售出票号为: 19
===> 售票员: Thread-6, 售出票号为: 18
===> 售票员: Thread-5, 售出票号为: 17
===> 售票员: Thread-1, 售出票号为: 16
===> 售票员: Thread-3, 售出票号为: 15
===> 售票员: Thread-9, 售出票号为: 14
===> 售票员: Thread-7, 售出票号为: 12
===> 售票员: Thread-8, 售出票号为: 11
===> 售票员: Thread-4, 售出票号为: 10
===> 售票员: Thread-2, 售出票号为: 9
===> 售票员: Thread-0, 售出票号为: 8
===> 售票员: Thread-6, 售出票号为: 7
===> 售票员: Thread-5, 售出票号为: 6
===> 售票员: Thread-1, 售出票号为: 5
===> 售票员: Thread-3, 售出票号为: 4
===> 售票员: Thread-9, 售出票号为: 3
===> 售票员: Thread-7, 售出票号为: 2
===> 售票员: Thread-8, 售出票号为: 1
*/

多线程卖票问题解决1 (synchronized 锁)

public class BuyTicketsMultiThreads {

  private static volatile int tickets = 30;

  public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
      new Thread(() -> {
        while (true) {
          if (tickets > 0) {
            synchronized (BuyTicketsMultiThreads.class) {
              if (tickets > 0) {
                System.out.println("===> 售票员: " + Thread.currentThread().getName() + ", 售出票号为: " + tickets);
                tickets--;
              }
            }
          } else {
            break;
          }
        }
      }).start();
    }
  }
}

多线程卖票问题解决2 (并发包工具类)

public class BuyTicketsWithConCurrent {
    private static final AtomicInteger TICKETS = new AtomicInteger(30);

    public static void main(String[] args) {
      for (int i = 0; i < 10; i++) {
        new Thread(() -> {
          while (true) {
            if (TICKETS.get() > 0) {
             System.out.println("===> 售票员: " + Thread.currentThread().getName() + ", 售出票号为: " + TICKETS.getAndDecrement());
            } else {
              break;
            }
          }
        }).start();
      }
    }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值