看了一下线程的知识,写了一段线程同步的代码,结果却没按照想的结果来,就想肯定是没有理解,网上 看了一下别人写的,改了一下代码,结果也算是按照想的来了。现在总结一下线程同步。
线程也是处理具有某个功能的一段代码,只是它的运行机制有点不同,它是在进程中的,一个进程有一个主线程,可通过主线程创建很多的子线程,线程启动之后,会按照它们的方式进行运行,不受程序员控制,不知道线程如何运行完,运行的结果也不相同。
在线程这一块需要知道线程所使用的资源:CPU和内存资源。线程根据CPU的时间片轮转来切换;线程可以访问所在对象的内存资源。
1.单对象多线程:共享变量和执行步骤
2.多对象多线程
写个小例子,好体会:
public class ThreadTestExample {
public static void main(String []args)
{
ThreadA examA = new ThreadA();
Thread threadExamA = new Thread(<span style="color:#ff6666;">examA</span>,"ThreadA");
// ThreadA examB = new ThreadA();
Thread threadExamB = new Thread(<span style="color:#ff6666;">examA</span>,"ThreadB"); <span style="color:#ff6666;">//threadExamA和threadExamB使用同一个对象examA,所以他们访问同一内存区</span>
threadExamA.start();
threadExamB.start();
}
}
class ThreadA implements Runnable
{
String name;
double money = 100000; //money在这里定义的是全局变量,所以<span style="color:#ff6666;">threadExamA和threadExamB都可以访问到它,所以应该确保有顺序的访问</span>
@Override
public void run() {
// TODO Auto-generated method stub
synchronized(this) //使用synchronized关键字同步这两个线程,一个访问完成后一个才能访问,this指代的是examA这个对象
{
if(Thread.currentThread().getName().equals("ThreadA"))
{
for(int i=0;i < 5; i++)
{
money -= 20000;
try{
Thread.sleep(1000);
}catch(InterruptedException e)
{}
System.out.printf("\n%s","I am ThreadA,"+"I have money:"+money+";");
}
}
if(Thread.currentThread().getName().equals("ThreadB"))
{
for(int i=0;i < 5; i++)
{
money += 20000;
try{
Thread.sleep(1000);
}catch(InterruptedException e)
{}
System.out.printf("\n%s","I am ThreadB,"+"I have money:"+money+";");
}
}
}
}
}
里面的注释只是解释了单对象多线程运行时,要注意内存中的全局变量,如果将money这个变量写到run方法中,则它表示局部变量,那么这两个线程则访问的不是同一个变量,输出的结果肯定是不一样的。
单对象多线程要注意的是线程访问的变量是全局变量还是局部变量,如果是全局变量,一定要注意线程的同步,用synchronized来标识同步,这个关键字可以按照上面那样写,也可以写在方法前面,这个方法在run中调用。如果是局部变量,那么它们访问的则不是同一个,运行结果也就没有影响。
使用多对象多线程,那么表示的意思是每个线程的访问空间都不一样,那么他们处理的结果之间不会相互影响。要注意不管是全局变量还是局部变量,都只在一个线程中起作用。
使用ThreadLocal机制
ThreadLocal是JDK引入的一种机制,它用于解决线程间共享变量,使用ThreadLocal声明的变量,即使在线程中数据全局变量,针对每个线程来讲,这个变量也是独立的。
下面是一个例子:
解决共享变量问题方案三
class MyRunner3 implements Runnable
{
public ThreadLocal<Integer> tl = new ThreadLocal<Integer>();
public void run()
{
System.out.println(Thread.currentThread().getName() + " Start.");
for (int i = 0; i <= 100; i++)
{
if (tl.get() == null)
{
tl.set(new Integer(0));
}
int sum = ((Integer)tl.get()).intValue();
sum+= i;
tl.set(new Integer(sum));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " --- The value of sum is " + ((Integer)tl.get()).intValue());
System.out.println(Thread.currentThread().getName() + " End.");
}
}
private static void sharedVaribleTest4() throws InterruptedException
{
MyRunner3 runner = new MyRunner3();
Thread thread1 = new Thread(runner);
Thread thread2 = new Thread(runner);
thread1.setDaemon(true);
thread2.setDaemon(true);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
未完待续...