多线程创建方式及线程安全问题

1.创建线程方式

一:  创建线程方式一继承Thread类

public clsss MyThread extends Thread{

//重写run方法,设置线程任务

Run(){

}

}

main(){

new MyThread().start();

}

获取线程名称:

Thread.currentThread()获取当前线程对象

Thread.currentThread().getName();获取当前线程对象的名称

二:创建线程方式—实现Runnable接口

创建线程的步骤。

1、定义类实现Runnable接口。

2、覆盖接口中的run方法。。

3、创建Thread类的对象

4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。

5、调用Thread类的start方法开启线程。

l  代码演示:

public class Demo02 {

public static void main(String[] args) {

//创建线程执行目标类对象

Runnable runn = new MyRunnable();

//将Runnable接口的子类对象作为参数传递给Thread类的构造函数

Thread thread = new Thread(runn);

Thread thread2 = new Thread(runn);

//开启线程

thread.start();

thread2.start();

for (int i = 0; i < 10; i++) {

System.out.println("main线程:正在执行!"+i);

}

}

三:两种方法的使用比较

第二种方式实现Runnable接口避免了单继承的局限性,所以较为常用。实现Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。

第一种方式继承Thread类,线程对象和线程任务耦合在一起。一旦创建Thread类的子类对象,既是线程对象,又有线程任务。

实现runnable接口,将线程任务单独分离出来封装成对象,类型就是Runnable接口类型。Runnable接口对线程对象和线程任务进行解耦。

2     线程安全

如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

线程不安全:

1.     单线程没有线程安全问题

2.     多线程没有使用相同的内容,也会不出现安全问题

3.     多线线程使用了同一个资源,可能会出现线程安全问题

一:使用同步代码块解决线程安全问题

synchronized(锁对象){

可能出现安全问题的代码

(访问了共享数据的代码)

}

同步代码块: 在代码块声明上 加上synchronized

synchronized (锁对象) {

可能会产生线程安全问题的代码

}

同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全。

使用同步代码块,对电影院卖票案例中Ticket类进行如下代码修改:

publicclass Ticket implements Runnable {

//共100票

intticket = 100;

//定义锁对象

Object lock = new Object();

@Override

publicvoid run() {

//模拟卖票

while(true){

//同步代码块

synchronized (lock){

if (ticket > 0) {

//模拟电影选坐的操作

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--);

}

}

}

}

}

注意:保证锁对象要唯一

二:使用同步方法解决线程安全问题

1.把访问共享数据的代码,提取出来放在一个方法中

2.在方法上增加一个同步关键字

修饰符 synchronized 返回值类型 方法名(参数列表){

出现了安全问题的代码

(使用了共享数据的代码)

}

l  同步方法:在方法声明上加上synchronized

public synchronized void method(){

可能会产生线程安全问题的代码

}

        同步方法中的锁对象是 this

使用同步方法,对电影院卖票案例中Ticket类进行如下代码修改:

publicclass Ticket implements Runnable {

//共100票

intticket = 100;

//定义锁对象

Object lock = new Object();

@Override

publicvoid run() {

//模拟卖票

while(true){

//同步方法

method();

}

}

//同步方法,锁对象this

publicsynchronizedvoid method(){

if (ticket > 0) {

//模拟选坐的操作

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--);

}

}

}

l  静态同步方法: 在方法声明上加上static synchronized

public static synchronized void method(){

可能会产生线程安全问题的代码

}

静态同步方法中的锁对象是 类名.class

Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能。

我们使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对电影院卖票案例中Ticket类进行如下代码修改:

publicclass Ticket implements Runnable {

//共100票

intticket = 100;

//创建Lock锁对象

Lock ck = new ReentrantLock();

@Override

publicvoid run() {

//模拟卖票

while(true){

//synchronized (lock){

ck.lock();

if (ticket > 0) {

//模拟选坐的操作

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--);

}

ck.unlock();

//}

}

}

}

时间: 2024-10-14 21:23:24

多线程创建方式及线程安全问题的相关文章

关于CoreData和SQLite多线程访问时的线程安全问题

http://www.jianshu.com/p/95db3fc4deb3 关于CoreData和SQLite多线程访问时的线程安全问题 数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常用的两种数据持久化存储方式:CoreData和SQLite,两者都需要设置线程安全,在这里以FMDB来解释对SQLite的线程安全访问. 一:FMDB的线程安全:(以读取图片为例) 1.没有线程安全的执行方式: //****

设计模式——单例模式(Java)——考虑多线程环境下的线程安全问题

设计模式--单例模式(Java)--考虑多线程环境下的线程安全问题 一:单例模式概念 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例 二:单例模式的实现方式 特别注意,在多线程环境下,需要对获取对象实例的方法加对象锁(synchronized) 方式一:(懒汉式)程序执行过程中需要这个类的对象,再实例化这个类的对象 步骤: 1.定义静态私有对象 2.构造方法私有化保证在类的外部无法实例化该类的对象 3.定义对外开放的静

JAVA-初步认识-第十二章-多线程创建方式一继承

一. 既然是创建线程,那么线程应该怎么创建?在没有学习java之前,这些程序是谁在操作执行的呢?是由我们所在的操作系统来完成的.Windows里面有个任务管理器,它来管理这些任务,它来创建这些进程,并来创建进程中所用的线程.是由系统来完成的,我们无法直接使用系统来帮我们做这件事情.解决问题的时候,首先想到的是java中是否有给我们提供能解决该问题的对象,尤其是线程还走了系统.你不玩java,它没有多线程,因为windows具备这能力,它在帮你做这个分配呢.我们是做不了的,我们就想说java是否也

Java之多线程创建方式

多线程的由来 我们在之前,学习的程序在没有跳转语句的前提下,都是由上至下依次执行,那现在想要设计一个程序,边打游戏边听歌,怎么设计?要解决上述问题,咱们得使用多进程或者多线程来解决. 多线程的好处: 提高程序运行效率,让CPU的 使用率更高. 多个线程之间互不影响 关于多线程的一些名词解释 并发:指两个或多个事件在同一个时间段内发生. 并行:指两个或多个事件在同一时刻发生(同时发生). 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程:进程也是

关于线程的创建方式,线程池的作用

线程的创建方式: 1.线程继承Thread类,通过该对象的start()方法启动线程 2.线程实现Runnable接口,通过往Thread类构造传入Runnable对象,thread.start()启动线程. 3.线程实现Callable接口.Callable相当于run方法有返回值的Runnable,与Future结合使用(接收返回值使用Future). 线程池的使用,为什么使用线程池? 复用线程,使用工作队列,避免无限制创建线程.重用线程降低开销,请求到达时,线程已存在,减少创建线程的等待时

多线程 创建子父线程 保证一件事 子线程执行三次后 父线程执行5次 循环10次

package Thread; /** * 创建子父线程 保证一件事 子线程执行三次后 父线程执行5次 循环10次 * 父线程main线程则为Console台项目的主线程 * 在main线程中调用了start线程则为子线程 * */ public class FatherAndSonTest { public static void main(String[] args) { final FatherAndSon fs = new FatherAndSon(); new Thread(new R

CoreData和SQLite多线程访问时的线程安全问题

数据库读取操作一般都是多线程访问的.在对数据进行读取时,我们要保证其当前状态不能被修改,即读取时加锁,否则就会出现数据错误混乱.IOS中常用的两种数据持久化存储方式:CoreData和SQLite,两者都需要设置线程安全,在这里以FMDB来解释对SQLite的线程安全访问. 一:FMDB的线程安全:(以读取图片为例) 1.没有线程安全的执行方式: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

多线程创建方式

1.继承Thread类创建多线程:继承java.lang.Thread类,重写Thread类的run()方法,在run()方法中实现运行在线程上的代码,调用start()方法开启线程. 2.实现Runable接口:实现java.lang.Runnable接口,重写run()方法,在run()方法中实现运行在线程上的代码. 3.两种多线程方式比较:这两种显示的创建线程的方式,我们在实际编程中都不用,要用线程池进行统一的资源管理. (1)Runable方法将线程同程序代码.数据有效的分离,代码相对整

多线程(三)-- 线程安全问题

安全解决 -- 互斥锁@synchronized(self) { //开始加锁,操作} 优:解决多线程抢夺资源产生的数据安全问题缺:消耗CPU资源多 使用前提:多条线程执行一块代码时加锁 线程同步:@synchronized()多条线程在同一条线上执行(按顺序执行,与线程并发不同) nonatomic 与 atomicatomic保护线程安全,自动加锁为setter加锁 对比atomic:线程安全,消耗大量资源nonatomic:非线程安全,适合内存小的移动设备