Forget Everything In My Life.

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

Java中的线程

一个程序的运行需要启动一个应用进程,一个进程可以创建多个线程,帮助应用完成多任务操作,实现并发运行。在Java中线程是被封装成Thread类,进行多线程操作时只需要继承一个Thread类,实现自己的功能即可,然后开启此线程,或者你也可以实现一个Runnable接口,然后将其传递给Thread对象,然后再启动它。

线程的创建于启动继承Thread

创建一个类并继承Thread类,然后实现Thread类的run方法,在run方法内填上自己的代码,然后创建这个自定义类,并调用其start方法来启动这个自定义线程。

// 引入Threadimport java.lang.Thread;/** * 创建自己的Thread,实现run方法(放上自己要执行的内容) */class MyThread extends Thread {/*** 覆盖超类Thread的run方法*/() {for(int i=0; i<10; i++) {System.out.println(“第” + i + “次循环”);}}}class ThreadDemo1 {(String[] args) {// 创建一个自定义线程,并且启动它new MyThread().start();}}/* 程序输出:第0次循环第1次循环第2次循环第3次循环第4次循环第5次循环第6次循环第7次循环第8次循环第9次循环*/实现Runnable

一个实现过Runnable的对象都可以被一个Thread对象所执行,

import java.lang.Thread;import java.lang.Runnable;/** * 创建一个类,实现Runnable接口。 */class MyRunnable implements Runnable {/*** 实现Runnable的run方法*/() {for(int i=0; i<5; i++) {System.out.println(“Runable:第” + i + “次循环”);}}}class ThreadDemo2 {(String[] args) {Thread(new MyRunnable()).start();}}/* 程序输出:Runable:第0次循环Runable:第1次循环Runable:第2次循环Runable:第3次循环Runable:第4次循环*/synchronized的使用

既然是多线程,那么就会出现多线程的问题,,如同时访问同一资源,从而产生意料之外的结果,这是我们所不想看到的。在Java中可以很简单的解决这个问题,使用synchronized对操作进行加锁,synchronized可以对对象加锁,也可以对函数进行加锁。下面对比一下未使用synchronized和使用synchronized的不同之处。

未使用synchronized的情况import java.lang.Thread;import java.lang.Runnable;class MyRunnable implements Runnable {i=0;() {for(; i<10; i++) {try {Thread.sleep(10);} catch(Exception e) {}print(i);}}(int k) {System.out.println(k);}}class Demo {(String[] args) {MyRunnable r = new MyRunnable();new Thread(r).start();new Thread(r).start();}}

可以看到结果不正确,因为两个线程可能会同时进入线程,然后打印出两个相同的值。

使用了synchronized后的情况import java.lang.Thread;import java.lang.Runnable;class MyRunnable implements Runnable {i=0;() {synchronized(this) {for(; i<10; i++) {try {Thread.sleep(10);} catch(Exception e) {}print(i);}}}(int k) {System.out.println(k);}}class Demo {(String[] args) {MyRunnable r = new MyRunnable();new Thread(r).start();new Thread(r).start();}}

当对for进行加锁处理后,便不会同时两个线程进入循环,这样打印的数字便不会出错。

synchronized的加锁对象会有一个标志位(0/1),默认的情况下是0,当线程执行到synchronized的加锁对象后如果对象的标志位为0,那么将其设置为1,否则等待。这个标志位可以称之为“锁旗标”。这样以来便可以实现线程同步。 虽然synchronized解决了多线程的不安全问题,但是也是有一定的弊端的,它会降低程序的执行效率,所以,synchronized不可以随意放置,应尽量将其放到必须使用的位置上。如单例模式的一个例子:

{private Single mInstance;private Single(){}public static Single getInstance() {if(mInstance == null) {synchronized(Single.class) {if(mInstance == null) {mInstance = new Single();}}}return mInstance;}}

这里的synchronized可以加在getInstance()前面,但是这样会大大降低执行效率,也可以去掉外层的if(mInstance == null),但是这样也会增加不必要的判断,以为如果mInstance已经创建后便不需要锁了。若此以来,上面这种写法是最好的。最内层的if判断有必要说明一下,可以假设这样一种情况,两个线程都执行到第一个if的后面,那么,如果没有内层的if判断的话,mInstance会被创建两次,所以,内层的if是不可或缺的。

wait和notify的使用

wait和notify是Object对象中的两个方法,其作用是用于多线程中的控制,如想使用两个线程交替打印出Odd和Even时,具体代码如下:

import java.lang.Thread;import java.lang.Runnable;class Temp {flag = false;}class Odd implements Runnable{() {while(true) {if(Temp.flag) {try {wait();} catch(Exception e) {}}System.out.println(“Odd”);Temp.flag = !Temp.flag;try {notify();} catch(Exception e) {}}}}class Even implements Runnable {() {while(true) {if(!Temp.flag) {try {wait();} catch(Exception e) {}}System.out.println(“Even”);Temp.flag = !Temp.flag;try {notify();} catch(Exception e) {}}}}class Demo {(String[] args) {new Thread(new Odd()).start();new Thread(new Even()).start();}}

当然除了notify方法,还有notifyAll方法,用于唤醒所有线程。

Lock的使用力微休负重,言轻莫劝人。

Forget Everything In My Life.

相关文章:

你感兴趣的文章:

标签云: