—————————— ASP.Net+Android+IOS开发、.Net培训、期待与您交流!——————————
线程是一个程序里不同的执行路径
多线程创建的两种方法:
1、继承Thread类。
①定义类继承Thread。
②复写Thread类中的run方法。
③调用线程的start方法,该方法有两个作用:启动线程,调用run方法。
发现运行结果每一次都不同,
因为多个线程都获取cpu的执行使用权,cpu执行到谁,谁就运行。
在某一个时刻,只能有一个程序在运行。(多核除外)
cpu在做着快速切换,以达到看上去同时运行的效果。
我们可以形象的把多线程的运行行为在互相抢夺cpu的执行权。
这就是多线程的特性,随机性。谁抢到谁执行,至于执行多长时间,cpu说的算。
2、通过实现Runnable接口线程创建
(1).定义一个类实现Runnable接口,重写接口中的run()方法。在run()方法中加入具体的任务代码或处理逻辑。
(2).创建Runnable接口实现类的对象。
(3).创建一个Thread类的对象,需要封装前面Runnable接口实现类的对象。(接口可以实现多继承)
(4).调用Thread对象的start()方法,启动线程
采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。
采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。
class Speak extends Thread{
public void run(){
for(int i=0;i<80;i++){
System.out.println("speak="+i);
}
}
}
public class testthread{
public static void main(String[] args){
Speak s = new Speak();
Write w = new Write();
s.start();
new Thread(w).run() ;
for(int i=0;i<80;i++){
System.out.println("main="+i);
}
}
}
class Write implements Runnable{
public void run(){
for(int i=0;i<80;i++){
System.out.println("write="+i);
}
}
}
class Speak extends Thread{
public int nub;
public void run(){
for(nub=0;nub<80;nub++){
System.out.println("speak="+nub);
yield();
//暂停当前正在执行的线程对象,并执行其他线程。
}
}
}
public class TestThread{
public static void main(String[] args) throws Exception{
Speak s = new Speak();
Write w = new Write();
s.start();
new Thread(w).run() ;
s.join();
System.out.println("Thread(Speack)="+s.nub);
for(int i=0;i<10;i++){
System.out.println("main="+i);
}
}
}
class Write implements Runnable{
public void run(){
for(int i=0;i<80;i++){
System.out.println("write="+i);
}
}
}
由上可知道join方法的用法:主线程生成并起动了子线程,而子线程里要进行大量的耗时的运算(这里可以借鉴下线程的作用),当主线程处理完其他的事务后,需要用到子线程的处理结果,这个时候就要用到join();方法了。
锁的机制:synchronized(互斥锁)
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.Java线程死锁是一个经典的多线程问题,因为不同的线程都在等待那些根本不可能被释放的锁,从而导致所有的工作都无法完成。
关于 多线程死锁
Java线程死锁是一个经典的多线程问题,因为不同的线程都在等待那些根本不可能被释放的锁,从而导致所有的工作都无法完成
经典问题,wiki百科哲学家吃饭问题
简单解决办法是将锁加粗。
class Ticket implements Runnable{
private int tick = 1000;
Object obj = new Object();
boolean flag = true;
public void run(){
if(flag){
while(true){
synchronized(obj){
show();
}
}
}
else
while(true)
show();
}
public synchronized void show()//this{
synchronized(obj){
if(tick>0){
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....code : "+ tick——);
}
}
}
}
class DeadLock{
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(Exception e){}
t.flag = false;
t2.start();
}
}
—————————— ASP.Net+Android+IOS开发、.Net培训、期待与您交流!——————————