java-线程Thread&线程不安全

java-线程Thread&线程不安全,第1张

一、 线程

1.定义:一个程序中不同的工作分支
2.如何实现:

  • java是面向对象的语言,所有的事物都是对象,包括线程。

  • java中线程的一种实现方式是继承Thread类。

  • 每个线程都有自己的工作,定义线程的时候要定义好这个线程需要做什么。线程对象需要做的工作定义在run()方法中。即定义好这个继承Thread的子类的功能是什么,这个子类的实例化对象就全都是做这种功能的。

  • 线程的启动要用start()方法,而不是run()方法。

    代码示例:

package com.easy;

public class Easy {

	public static void main(String[] args) {
		T1 t1 = new T1();
		t1.start();
	}
}


class T1 extends Thread{
	@Override
	public void run() {
		for(int i = 1; i <= 20; i++) {
			//getName()方法用来获取线程名字, this代表当前实例对象 
			System.out.println(i+"----"+this.getName());
		}
	} 
}

3.线程是异步进行的,彼此之间不受影响
代码实例:

package com.easy;

public class Easy {

	public static void main(String[] args) {
		T1 t1 = new T1();
		T1 t2 = new T1();
		t1.start();
		t2.start();
	}
}


class T1 extends Thread{
	@Override
	public void run() {
		for(int i = 1; i <= 10; i++) {
			//getName()方法用来获取线程名字, this代表当前实例对象 
			System.out.println(i+"----"+this.getName());
		}
	} 
}

运行结果:
1----Thread-0
1----Thread-1
2----Thread-1
3----Thread-1
4----Thread-1
5----Thread-1
2----Thread-0
3----Thread-0
6----Thread-1
4----Thread-0
7----Thread-1
5----Thread-0
8----Thread-1
6----Thread-0
7----Thread-0
8----Thread-0
9----Thread-0
9----Thread-1
10----Thread-0
10----Thread-1

从运行结果可以看出,两个线程异步进行,异步进行也就是说,两个进程互不影响,同时执行。

4.区分mian和线程对象
程序执行有主线程也就是main线程,在main方法中,实例化线程对象,并调用其start()方法开启线程之后,主线程不会等待该线程对象执行,而是会直接继续执行下一句。
代码实例:

package com.easy;

import java.util.ArrayList;

public class Easy1 {

	public static void main(String[] args) {
		ArrayList list = new ArrayList(); //创建容器对象
		//定义线程对象
		T t1 = new T(list);
		//T t2 = new T(list);
		t1.start();
		//t2.start();
		System.out.println(list.size());
	}
}


class T extends Thread{
	ArrayList list;
	public T(ArrayList list) {
		this.list = list;
	}
	
	@Override
	public void run() {     //往数组中添加200个数据
		for(int i = 0; i < 200; i++) {
			list.add(i);
		}
	}
}

执行结果: 0

出现这个执行结果的原因就是,一开始list为空,当t1线程开始执行后,主线程不会等待t1执行,而是直接执行下一行代码,也就是输出list的size();
此时我们可以让主线程休息一会,让t1线程执行完毕。可以在t1.start();后加入一行Thread.sleep(1000); 让主线程休息1s,这样t1就可以执行完毕。

二、线程安全

线程安全即指数据安全,也就是数据不错乱。
当多个线程 *** 作一个数据时,会产生异常结果。
举例说明:假设开辟了一个数组,两个线程同时开始往数组存数据,对于i位置,可能两个数组同时检测到该位置没有数据,然后都往这个位置存放数据,那么就会造成数据的覆盖。这就产生了异常结果,也就是线程不安全。
代码示例:

package com.easy;

import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;

public class Easy2 {

	public static List list = new LinkedList();
	public static void main(String[] args) {
		Th t1 = new Th();
		t1.start();
		Th t2 = new Th();
		t2.start();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(list.size());
	}
	
	public static void add(Object obj) {
		list.add(obj);
	}
}


class Th extends Thread{
	@Override
	public void run() {
		for(int i = 0; i < 200; i++) {
			Easy2.add(i);
		}
	}
}
运行结果(多次): 387
                  375
                  386

解决: synchronized关键字
synchronized关键字可以标注某个代码块是同步代码块。也就是说,被synchronized关键字修饰的代码块,当有多个线程准备运行此代码块时,同一时间只有一个线程可以运行此代码块。

public static syncharonized void add(Object obj) {
		list.add(obj);
	}
运行结果:400

同步和异步比较:
同步更安全,不会发生数据错乱
异步处理数据速度更快,但可能引发数据错乱

transient关键字???
临时的,不稳定的,每次用它都要从新检测他的值。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/729428.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存