锁和多线程:线程创建3种方式(一)

线程 锁Synchronized

  • 1.线程创建
  • 2.线程安全

搞明白 线程 多线程系列

1.线程创建

线程创建常见的三种方式:

  1. 继承Thread类
  2. 实现Runnable接口
  3. 实现Callable接口

第三种方式有异步调用效果,类似js中的ajax可以接收返回值,其余两种不能.

package thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @Author lyf
 * @Date 2018/11/17 0017 13:38
 */
public class MyThread {
  public static void main(String[] args) throws ExecutionException, InterruptedException {
    // 继承Thread类
    new Thread01("线程1").start();
    // 实现Runnable接口
    new Thread(new Thread02(), "线程2").start();
    // 实现Callable接口
    FutureTask<String> futureTask = new FutureTask<>(new Thread03());
    futureTask.run();
    while (futureTask.isDone()) { // 判断线程是否运行结束
      System.out.println("结果: " + futureTask.get());// 获取结果
      return;
    }
  }
}

class Thread01 extends Thread {
  public Thread01(String name) {
    super(name);
  }

  @Override
  public void run() {
    System.out.println(Thread.currentThread().getName() + "执行...");
  }
}

class Thread02 implements Runnable {

  @Override
  public void run() {
    System.out.println(Thread.currentThread().getName() + "执行...");
  }
}

class Thread03 implements Callable<String> {

  @Override
  public String call() throws Exception {
    Thread.sleep(3000);
    System.out.println(Thread.currentThread().getName() + "执行...");
    return "hello";
  }
}

2.线程安全

多线程下访问数据会有线程安全问题.比如买火车票,只有10张票20人买,那就要确保不能卖重,不能多卖.看下面例子:

package thread;

/**
 * @Author lyf
 * @Date 2018/11/17 0017 14:13
 */
public class Ticket {
  private int num = 10;

  public void buy() {
    if (num > 0) {
      try {
        Thread.sleep((long) (Math.random() * 100));
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("抢到第" + num-- + "张票...");
    } else {
      System.out.println("票已售罄...");
    }
  }

  public static void main(String[] args) {
    final Ticket ticket = new Ticket();
    for (int i = 0; i < 200; i++) {
      new Thread(() -> { ticket.buy(); }).start();
    }
  }
}

多线程操作下,就会出现多卖的情况.如果要解决,可以通过加锁synchronized方式来实现.把上边的代码修改如下:

public synchronized void buy() {
  ...
}

可以保证不存在多卖情况.

原文地址:https://www.cnblogs.com/linyufeng/p/9991807.html

时间: 2024-08-30 02:14:46

锁和多线程:线程创建3种方式(一)的相关文章

python 线程(创建2种方式,守护进程,锁,死锁,递归锁,GIL锁,其他方式)

###############总结############ 线程创建的2种方式(重点) 进程:资源分配单位    线程:cpu执行单位(实体) 线程的创建和销毁的开销特别小 线程之间资源共享,是同一个进程中的资源共享,会涉及到安全问题,所以需要加锁解决 锁:牺牲了效率,保证了数据安全(重点) 死锁现象:出现在嵌套的时候,双方互相抢对方已经拿到的锁,导致双方互相等待(重点) 递归锁: 解决了死锁现象(重点) rlock 首先本身就是个互斥锁,维护了一个计数器,每次acquire+1,release

【java多线程】多线程的创建三种方式--笔记

申明:线程的概念以及进程的相关概念,可以参考网络上其他资料,这里只讨论多线程是怎么实现. 一.多线程的简单理解 明白什么是多线程,小生通俗一点的理解为:在一个程序里,我想同时让这个程序完成多个任务. 比如:让主函数 main 在打印1~100之间的所有整数的时候,要求在主函数打印到 20 的时候,再运行另一个类里的程序,让它打印10~100之间的所有整数. 这里忽略同进程内的多线程之间的抢占时间问题,上面的举例需求是要求一个程序只要有发生同时运行俩个程序的情况就行,即不准出现无论程序跑多少次都是

死锁现象与解决方案,开启线程的2种方式,守护线程,线程VS进程,线程互斥锁,信号量

死锁现象与解决方案 from threading import Thread,Lock,active_count import time mutexA=Lock() # 锁1 mutexB=Lock() # 锁2 class Mythread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print('%s 拿到A锁' %self.name) mutexB.acquire() print('%

Python36 1.joinablequeue 2.线程理论 3.多线程对比多进程 4.线程的使用方式 4.1.产生 线程的两种方式 4.2.守护线程 4.3.线程安全问题 4.3.1.互斥锁 4.3.2.死锁 4.3.3.可重入锁 4.3.4.信号量

复习1.守护进程2.互斥锁(解决数据错乱的方法)3.IPC(进程间通讯)4.生产者与消费者模型 详解:1.守护进程 一个进程可以设为另一个进程的守护进程 特点:被守护的进程结束时,守护进程也会随之结束 本质:父进程交给子进程一个任务,然而父进程 先于子进程结束了,子进程的任务也就没有必要 继续执行了 格式:开始前加 p.daemon=True 2.互斥锁(解决数据错乱的方法)方法一:互斥锁 互斥 互相排斥 锁的本质:一个标志 标志的两个状态: 1.锁定 2.未锁定 什么时候用? 当多个进程要操作

java多线程---创建线程的几种方式

创建线程的几种方式 在并发编程中,创建线程是我们经常会做的事情,那么一般来说,创建线程有4种方式: 1.继承Thread类. 2.实现Runnable接口. 3.实现Callable接口,结合FutureTask来使用. 4.利用线程池的方式来实现. 继承Thread创建线程 public class ThreadTest1 extends Thread { @Override public void run() { try { Thread.sleep(1000); } catch (Inte

java创建线程的三种方式及其对比

Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务.因此把run()方法称为执行体. (2)创建Thread子类的实例,即创建了线程对象. (3)调用线程对象的start()方法来启动该线程. package com.thread; public class FirstThreadTest extends Thread{ int i = 0; //重写run方法,run方法的方

java创建线程的三种方式及其对照

Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类.并重写该类的run方法,该run方法的方法体就代表了线程要完毕的任务.因此把run()方法称为运行体. (2)创建Thread子类的实例,即创建了线程对象. (3)调用线程对象的start()方法来启动该线程. package com.thread; public class FirstThreadTest extends Thread{ int i = 0; //重写run方法.run方法的方

并发编程(壹):创建线程的三种方式及其对比

创建线程的三种方式及其对比 1. 继承 Thread类 (1). 继承Thread类.并重写run()方法,该方法无参数,无返回值: (2). 创建子类实例,并实例化对象: (3). 通过start()方法启动,注意:不是通过run()方法启动. public class ThreadDemo extends Thread{ public void run(){ System.out.println("继承Thread创建线程的."); } } public class ThreadA

创建线程的两种方式比较Thread VS Runnable

1.首先来说说创建线程的两种方式 一种方式是继承Thread类,并重写run()方法 1 public class MyThread extends Thread{ 2 @Override 3 public void run() { 4 // TODO Auto-generated method stub 5 6 } 7 } 8 //线程使用 9 MyThread mt = new MyThread(); //创建线程 10 mt.start(); //启动线程 另外一种方式是实现Runnabl