java 线程 api_java-API之多线程

初识多线程

进程:正在运行的程序。也就是代表了程序锁占用的内存区域。一个软件的运行,必须启动至少一个进程,也可以多个。

单线程:一个进程如果只启动了一个线程在干活,这个程序就是单线程程序

多线程:一个进程如果启动了多个线程在干活,这个程序就是多线程程序,执行效率高。

进程和线程的关系:一个软件的运行以来至少一个进程,进程的运行也是至少依赖一个线程,线程是调度运算的最小单位。(面试题)

并发:是指同一时刻,多个程序在抢占共享资源,同时抢占CPU来执行程序

并行:是指同一时刻,有多个CPU在干活,但是一个CPU只干一件事

线程的状态:新建状态、可运行状态、运行状态、终止状态、阻塞状态。

多线程编程

构造方法

Thread() 分配新的 Thread 对象。

Thread(Runnable target) 分配新的 Thread 对象。

Thread(Runnable target, String name) 分配新的 Thread 对象。

Thread(String name) 分配新的 Thread 对象。

常用方法

static Thread currentThread() 返回对当前正在执行的线程对象的引用。

long getId() 返回该线程的标识符。

String getName() 返回该线程的名称。

void run() 如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。

static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。

void setName(String name) 改变线程名称,使之与参数 name 相同。

void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

void stop() 已过时。 终止线程

实现多线程方法一——继承Thread类

1 public classTest2_Thread {2

3 public static voidmain(String[] args) {4

5 //创建线程

6 MyThread thread = new MyThread("线程1");7 //启动线程8 //start()从新建状态变成可执行状态,自动调用run方法

9 thread.start();10

11 MyThread thread2 = new MyThread("线程2");12 thread2.start();13

14 }15 }16

17

18 //创建多线程类 继承于 Thread 类

19 class MyThread extendsThread {20 publicMyThread() {21 super();22 }23

24 publicMyThread(String name) {25 super(name);26 }27

28 //把多线程业务写到run方法内

29 @Override30 public voidrun() {31 for (int i = 0; i < 10; i++) {32 //getName() 获取当前线程的名称

33 System.out.println(getName()+ "--"+i);34 }35 }36 }

实现多线程方法一——实现Runnable接口

public classTest3_Runnable {public static voidmain(String[] args) {//创建多个线程对象执行任务

MyRunnable runable = newMyRunnable();//把接口类型的对象,转成Thread类型,因为想调用Thread的start()启动线程——Thread(Runable target)

Thread thread = new Thread(runable,"线程1");//调用start()启动线程

thread.start();

Thread thread2= new Thread(runable,"线程2");

thread2.start();

}

}//创建实现类,实现Runnable接口

class MyRunnable implementsRunnable {//把多线程业务放在run方法内

@Overridepublic voidrun() {for (int i = 0; i < 10; i++) {//Thread.currentThread()获取当前正在执行任务的线程对象

System.out.println(Thread.currentThread().getName()+"=="+i);

}

}

}

Thread和Runable实现多线的比较

方式

优点

缺点

Thread

编写简单,如果需要访问当前线程,则无需使用Thread.currentThread()方法,直接使用this即可获得当前线程。

线程类已经继承了Thread类,所以不能再继承其他父类

Runnable

线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。

在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。

编程稍微复杂,如果要访问当前线程,则必须使用Thread.currentThread()方法。

多线程售票案例

1 public classTest1_MyTicket {2 public static voidmain(String[] args) {3 Runnable mt = newMyTicket();4

5 //创建线程

6 Thread t1 = new Thread(mt,"窗口1");7 //启动线程

8 t1.start();9 Thread t2 = new Thread(mt,"窗口2");10 t2.start();11 Thread t3 = new Thread(mt,"窗口3");12 t3.start();13 Thread t4 = new Thread(mt,"窗口4");14 t4.start();15 }16 }17

18

19 classMyTicket implements Runnable {20 int count = 100; //记录当前票的数量

21

22 @Override23 public voidrun() {24 while(true) {25 if(count > 0) {26 try{27 Thread.sleep(100); //让线程休息一会28 //Thread.currentThread().getName() 获取当前线程名称

29 System.out.println(Thread.currentThread().getName() + "==" + count--);30 } catch(InterruptedException e) {31 e.printStackTrace();32 }33 }else{34 break;35 }36 }37

38 }39 }

经过测试,我们发现以上代码出现以下问题:

问题1: 重复卖票,同一张票卖给了多人

问题2:超卖,也就是票数出现了负数

同步锁解决方案

异步:多个线程可以同时操作共享数据,互相不需要等待。效率较高,但是数据存在安全性问题。

同步:同一时刻只能有一个线程操作共享资源,相当于独占资源(其它线程必须等待其完成才能继续)。牺牲了程序的执行效率,提高了资源的安全性。

同步锁synchronized使用场景:将那些有多线程并发数据存在安全隐患的代码用同步包起来。它可以修饰代码块,也可以修饰方法,一般情况下使用代码块;如果方法里都是同步代码,可以把synchronized直接写在方法上。在保证解决数据安全的前提下,锁定的范围越小,程序的效率越高。多个线程,必须使用同一个锁(也就是关键字synchronized后面对象参数所指的对象,多个线程要使用同一对象,这样锁住共享资源,否则仍有安全隐患)。代码演示如下:

1 public classTest2_Synchronized {2 public static voidmain(String[] args) {3 Runnable run = newMyTicket2();4

5 Thread t1 = new Thread(run, "窗口1");6 t1.start();7 Thread t2 = new Thread(run, "窗口2");8 t2.start();9 Thread t3 = new Thread(run, "窗口3");10 t3.start();11 Thread t4 = new Thread(run, "窗口4");12 t4.start();13 }14 }15

16 classMyTicket2 implements Runnable {17 int count = 100;18

19 @Override20 public voidrun() {21 while (true) {22 //synchronized同步代码块,把所有的问题的代码包起来,来实现同步代码23 //必须是多个线程使用的是同一个对象

24

25 synchronized (this) { //synchronized后面参数中的对象,必须是多个线程使用的是同一个对象

26 if (count > 0) {27 try{28 Thread.sleep(10);29 } catch(InterruptedException e) {30 e.printStackTrace();31 }32 System.out.println(Thread.currentThread().getName() + "===" + count--);33

34 } else{35 break;36 }37 }38 }39 }40 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值