实现多线程首先有多种方法,其中的 2种:。1:extend Thread 这个类覆盖run方法。
2:implement Runable 借口 实现run方法。
2种方式都可以做到多线程。
但是也是有优缺点(不同之处)之分的 :
比如 继承的话 就不能同时继承其他的类了。这就是一个弊端。而用借口就不一样。可以多次实现。
再比如 使用继承的方法的话
Thread threa1=new Thread() ;
每次创建都是 新的线程。而用接口的方法的话。
Thread thread2=new Thread(target) ;//这里的target是 Ranable 对象。
每次新建的线程都是共享数据的,虽然不是同一个线程,但是却共享数据。
比如:
class window implements Runnable{
int a=500;
Object obj=new Object();
public void run() {
synchronized (obj) {
System.out.println(Thread.currentThread().getName());
a=a-1;;
System.out.println(a);
}
}
}
测试时
public static void main(String[] args) {
window w=new window();
Thread at2=new Thread(w);
Thread at3=new Thread(w);
Thread at4=new Thread(w);
at2.start();
at3.start();
at4.start();
;
}
发现a的数据是共享的。
如果用继承的话:
class thread1 extends Thread{
int a=500;
public void run() {synchronized(obj){System.out.println(Thread.currentThread().getName());a--;System.out.println(a);}}} 测试:static Object obj=new Object();
thread1 st1 = new thread1(); thread1 st2 = new thread1(); st1.start(); st2.start();
数据不共享。所以是有区别的。如果在a变量加上Static 的话还是可以实现数据共享的。
其实主要控制 共享数据就行了。造成这个的原因就是构造器不同。一个是无参数的构造。没有写入共享数据的对象。如果用带共享数据参数的方法创建线程对象。那就是线程安全的。
这里我还用了synchronized(c);方法实现线程安全。这里有2中办法实现线程安全。叫同步机制。
1:把你要对数据进行操作的代码放到代码块里面。
2: 声明同步方法
第一种 我上面用得就是。而要注意的一点就是。这个synchronized(c){}。他的参数为一个类!这个类必须是同一个对象。也就是说用来控制多个线程的锁必须是同一把锁。
这样的话如果用得接口方法。那他本来创建的线程都是共享数据的。里面的obj是属于同一个!同一把锁。
但如果用继承的方式的话,创建的线程属于多个,也保持是同一把锁的话,需要把锁的那个对象声明为static。才行。不然到不到线程安全的效果。
保持同一把锁的方法还有很多。不一一举例了。
第二种 就是在你要操作的函数上声明是 synchronized (修饰符)说明这个方法是同步方法。 它默认的锁为this。意思就是调用此方法的对象。必须保证这个对象是唯一的。不然会出错。不安全。
其实主要控制 操作的数据是共享的就行了。
用了多线程,意味着可能速度回有所减低。毕竟还要有cpu切换的时间。
其实多线程用了同步机制也就是相当于在代码块里面用单线程完成操作。
线程同步机制;还涉及到死锁 的问题。
造成这样的原因是多个线程分别占用对方所需要的资源。等待着对方的放弃。造成死锁。
比如:2个线程 用来实现线程安全的锁 都是 a和b 。其中一个线程要完成某种操作,这种操作的实现需要a和b锁的配合。而另一个线程也一样。这时候2个线程分别占用a和b中的一把锁,都需要对方的锁来完成自己的操作。就一直等待。。。形成死锁。
锁的原理图在这:
t1,t2,t3位线程。
obj为锁
其中一个线程抢到资源进去后,锁会变为红色,表示被占用。其他线程进不来。之道这个线程做完操作,释放锁。才能进行新一轮的抢资源。