继承Thread类
package com.myThread;
public class MyThread1 extends Thread{
@Override
public void run() {
super.run();
System.out.println("hello this is myThread");
}
}
package com.test;
import com.myThread.MyThread1;
public class MyTest1 {
public static void main(String[] args) {
MyThread1 thread1 = new MyThread1();
thread1.start();
System.out.println("main end");
}
}
打印结果
main end
hello this is myThread
实现Runnable接口
package com.myThread;
public class MyThread2 implements Runnable {
@Override
public void run() {
System.out.println("hello this is myThread2");
}
}
package com.test;
import com.myThread.MyThread1;
import com.myThread.MyThread2;
public class MyTest1 {
public static void main(String[] args) {
//MyThread1 thread1 = new MyThread1();
MyThread2 thread2=new MyThread2();
Thread thread=new Thread(thread2);
//thread1.start();
thread.start();
System.out.println("main end");
}
}
打印结果
main end
hello this is myThread2
实例变量和线程安全
- 非线程安全
非线程安全指的是多个线程访问统一对象的中的同一个实例变量进行操作时会出现值被更改、值不同步的情况.
package com.myThread;
public class MyThread3 extends Thread{
int count = 10;
@Override
public void run() {
super.run();
count--;
System.out.println(this.currentThread().getName()+":count="+count);
}
}
package com.test;
import com.myThread.MyThread3;
public class MyTest3 {
public static void main(String[] args) {
MyThread3 myThread3=new MyThread3();
Thread a = new Thread(myThread3,"a");
Thread b = new Thread(myThread3,"b");
Thread c = new Thread(myThread3,"c");
Thread d = new Thread(myThread3,"d");
Thread e = new Thread(myThread3,"e");
Thread f = new Thread(myThread3,"f");
a.start();
b.start();
c.start();
d.start();
e.start();
f.start();
}
}
打印结果
a:count=9
d:count=7
e:count=6
b:count=6
c:count=5
f:count=4
线程e和线程b同时访问count,出现非线程安全
- 使用synchronized实现线程安全
synchronized可以在任意对象以及方法上加锁,而加锁的这段代码称为“互斥区”
package com.myObject;
public class MyObject4 {
static String objName;
static String objPassword;
// synchronized public static void op(String name, String password) {//关键
public static void op(String name, String password) {
try {
objName = name;
objPassword = password;
if ("a".equals(objName))
Thread.sleep(50);
System.out.println(objName + "/" + objPassword);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.myThread;
import com.myObject.MyObject4;
public class MyThread4a extends Thread{
@Override
public void run() {
super.run();
MyObject4.op("a", "aa");
}
}
package com.myThread;
import com.myObject.MyObject4;
public class MyThread4b extends Thread{
@Override
public void run() {
super.run();
MyObject4.op("b", "bb");
}
}
package com.test;
import com.myThread.MyThread4a;
import com.myThread.MyThread4b;
public class MyTest4 {
public static void main(String[] args) {
MyThread4a myThread4a=new MyThread4a();
MyThread4b myThread4b=new MyThread4b();
myThread4a.start();myThread4b.start();
}
}
i- -和i+ +
自增和自减不是原子操作,所以会出现线程安全问题,用到的时候还是需要同步方法
如,System.out.println的内部实现是同步的,但是自增或者自减不是原子操作所以打印时可能会出现非线程安全。
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}