继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

java中的线程

米脂
关注TA
已关注
手记 492
粉丝 88
获赞 591

进程是指运行中的应用程序。每个进程都有自己独立的地址空间(内存空间)。

目前操作系统基本都支持多进程。



线程是轻量级的进程;

线程没有独立的地址空间(内存空间);

线程是由进程创建的(寄生在进程);

一个进程可以拥有多个线程,这就是多线程编程;

5baf289600014ec106140290.jpg


spacer.gif

 

 线程的5中状态:创建,可运行状态,运行状态;阻塞状态,死亡。

创建,可运行状态:cpu等是否空闲;

可运行状态,运行状态:cpu等是否空闲;

运行状态;阻塞状态:cpu等被别人抢占。

运行状态,死亡。:正常的走完。


只要应用程序涉及到并发就要用到多线程的编程。

 在java中一个类要当作线程来使用由两种方式:

1.继承Thread类,实现run方法;

2.实现Runnable接口,重写run方法;


publicclass TestThread extends Thread{ 
    
public TestThread(String name) {
        
super(name);
    } 

    
public void run() {
        
for(int i = 0;i<5;i++){
            
for(long k= 0; k <100000000;k++);
            System.out.println(
this.getName()+" :"+i);
        } 
    } 

    
publicstaticvoid main(String[] args) {
        Thread t1 = 
new TestThread("阿三");
        Thread t2 = 
new TestThread("李四");
        t1.start(); //开启线程 那么就会调用run方法
        t2.start(); 
    } 
}

另外:线程中Thread.sleep(1000)睡眠状态其实就是进入阻塞状态。并且释放cpu资源。



/** 
实现Runnable接口的类

* @author leizhimin 2008-9-13 18:12:10 
*/
 
publicclass DoSomethingimplements Runnable {
    
private String name;

    
public DoSomething(String name) {
        
this.name = name;
    } 

    
publicvoid run() {
        
for (int i = 0; i < 5; i++) {
            
for (long k = 0; k < 100000000; k++) ;
            System.out.println(name + 
": " + i);
        } 
    } 
}

 

/** 
测试Runnable类实现的多线程程序

* @author leizhimin 2008-9-13 18:15:02 
*/
 
publicclass TestRunnable {
    
publicstaticvoid main(String[] args) {
        DoSomething ds1 = 
new DoSomething("阿三");
        DoSomething ds2 = 
new DoSomething("李四");

        Thread t1 = new Thread(ds1);
        Thread t2 = new Thread(ds2);//此处是跟继承Thread的区别,还要创建一个线程对象,才可以调用start方法;多线程的运作,这个就是。


        t1.start(); 
        t2.start(); 
    } 
}

 

多线程的运用场景:坦克中的子弹。每隔多少秒,坐标持续变化。



同步问题提出

 

线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。

就是多个线程不加控制同时访问一个数据的时候,就会出现不规则的情况。

例如:两个线程ThreadAThreadB都操作同一个对象Foo对象,并修改Foo对象上的数据。

 

publicclass Foo {
    
privateint x = 100;

    
publicint getX() {
        
return x;
    } 

    
publicint fix(int y) {
        x = x - y; 
        
return x;
    } 
}

 

publicclass MyRunnableimplements Runnable {
    
private Foo foo =new Foo(); 

    
publicstaticvoid main(String[] args) {
        MyRunnable r = 
new MyRunnable();
        Thread ta = 
new Thread(r,"Thread-A"); 
        Thread tb = 
new Thread(r,"Thread-B"); 
        ta.start(); 
        tb.start(); 
    } 

    
publicvoid run() {
        
for (int i = 0; i < 3; i++) {
            
this.fix(30);
            
try {
                Thread.sleep(1); 
            } 
catch (InterruptedException e) {
                e.printStackTrace(); 
            } 
            System.out.println(Thread.currentThread().getName() + 
" :当前foo对象的x= " + foo.getX());
        } 
    } 

    
publicint fix(int y) {
        
return foo.fix(y);
    } 
}

 

运行结果:

Thread-A : 当前foo对象的x值= 40
Thread-B : 当前foo对象的x值= 40

Thread-B : 当前foo对象的x= -20
Thread-A : 
当前foo对象的x= -50
Thread-A : 当前foo对象的x值= -80
Thread-B : 当前foo对象的x值= -80


Process finished with exit code 0

 

从结果发现,这样的输出值明显是不合理的。原因是两个线程不加控制的访问Foo对象并修改其数据所致。

 

如果要保持结果的合理性,只需要达到一个目的,就是将对Foo的访问加以限制,每次只能有一个线程在访问。这样就能保证Foo对象中数据的合理性了。

 

在具体的Java代码中需要完成一下两个操作:

把竞争访问的资源类Foo变量x标识为private

步哪些修改变量的代码,使用synchronized关键字同步方法或代码。


  public int fix(int y) {
        synchronized (this) {
            x = x - y;
        }
        return x;

    }

采用synchronized保卫代码块就可以防止上述的状况,他的原理就是对象锁,排队上厕所,第一个线程完成啦,把门打开,第二个线程才可以用。

对象(this)里面可以换成任何类的对象,看门狗的意思,默认与0与1的标识。1表示为空,可以进入门。2表示有人。this指当前类。



线程死锁 :就是第一个线程完了之后但是没有把0变成1就走啦,导致后面的线程在继续的排队。


原文链接:http://www.apkbus.com/blog-846519-61883.html

打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP