Java多线程操作
来源:互联网 发布:pccillin云安全软件 编辑:程序博客网 时间:2024/05/23 01:26
Java中的线程
一个程序的运行需要启动一个应用进程,一个进程可以创建多个线程,帮助应用完成多任务操作,实现并发运行。在Java中线程是被封装成Thread
类,进行多线程操作时只需要继承一个Thread
类,实现自己的功能即可,然后开启此线程,或者你也可以实现一个Runnable
接口,然后将其传递给Thread
对象,然后再启动它。
线程的创建于启动
继承Thread
创建一个类并继承Thread
类,然后实现Thread
类的run
方法,在run
方法内填上自己的代码,然后创建这个自定义类,并调用其start
方法来启动这个自定义线程。
// 引入Threadimport java.lang.Thread;/** * 创建自己的Thread,实现run方法(放上自己要执行的内容) */class MyThread extends Thread { /** * 覆盖超类Thread的run方法 */ public void run() { for(int i=0; i<10; i++) { System.out.println("第" + i + "次循环"); } }}class ThreadDemo1 { public static void main(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方法 */ public void run() { for(int i=0; i<5; i++) { System.out.println("Runable:第" + i + "次循环"); } }}class ThreadDemo2 { public static void main(String[] args) { // 创建一个线程,并创建一个实现过Runnable的对象 // 构造它,然后再启动这个线程 new 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 { private static int i=0; public void run() { for(; i<10; i++) { try { Thread.sleep(10); } catch(Exception e) { } print(i); } } private void print(int k) { System.out.println(k); }}class Demo { public static void main(String[] args) { MyRunnable r = new MyRunnable(); new Thread(r).start(); new Thread(r).start(); }}
可以看到结果不正确,因为两个线程可能会同时进入线程,然后打印出两个相同的值。
002345678910
使用了synchronized
后的情况
import java.lang.Thread;import java.lang.Runnable;class MyRunnable implements Runnable { private static int i=0; public void run() { synchronized(this) { for(; i<10; i++) { try { Thread.sleep(10); } catch(Exception e) { } print(i); } } } private void print(int k) { System.out.println(k); }}class Demo { public static void main(String[] args) { MyRunnable r = new MyRunnable(); new Thread(r).start(); new Thread(r).start(); }}
当对for
进行加锁处理后,便不会同时两个线程进入循环,这样打印的数字便不会出错。
0123456789
synchronized
的加锁对象会有一个标志位(0/1),默认的情况下是0,当线程执行到synchronized
的加锁对象后如果对象的标志位为0,那么将其设置为1,否则等待。这个标志位可以称之为“锁旗标”。这样以来便可以实现线程同步。
虽然synchronized
解决了多线程的不安全问题,但是也是有一定的弊端的,它会降低程序的执行效率,所以,synchronized
不可以随意放置,应尽量将其放到必须使用的位置上。如单例模式的一个例子:
public class Single { 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 { public static boolean flag = false;}class Odd implements Runnable{ public void run() { 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 { public void run() { 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 { public static void main(String[] args) { new Thread(new Odd()).start(); new Thread(new Even()).start(); }}
当然除了notify
方法,还有notifyAll
方法,用于唤醒所有线程。
Lock的使用
JDK1.5之后,也就是Java5.0之后,增加了许多新的内容,如用于线程控制的一些类,Lock
的用法相当于synchronized
,Lock
中lock()
和unlock()
分别用于加锁和解锁,一般使用方法如下:
import java.lang.Runnable;import java.lang.Thread;import java.util.concurrent.locks.*;class Locks implements Runnable { private Lock lock = new ReentrantLock(); private int index = 0; public void run() { while(true) { lock.lock(); System.out.print(index + " "); try { Thread.sleep(100); } catch(Exception e) {} index ++; lock.unlock(); } }}class Demo { public static void main(String[] args) { Locks locks = new Locks(); new Thread(locks).start(); new Thread(locks).start(); new Thread(locks).start(); }}
这样便可以顺序打印出0 1 2 3 4 ···
。
通过Lock
的对象,我们可以创建Condition对象,如 Condition condition = lock.newCondition();
然后可以使用condition.await();
和condition.signal()
来暂停和唤醒线程,当然还有condition.signalAll()
来唤醒所有线程。
- JAVA多线程数据库操作
- JAVA多线程数据库操作
- JAVA的多线程操作
- Java多线程操作
- Java多线程操作
- java 多线程操作
- Java 多线程操作
- java操作多线程
- Java 多线程操作
- Java Thread 多线程 操作线程
- Java Thread 多线程 操作线程
- Java多线程--线程操作范例
- java 多线程操作同一个变量
- java 多线程+队列 ping 操作
- java 多线程基本操作总结
- JAVA多线程读写文件操作
- Java Thread 多线程 操作线程
- java多线程之批量操作
- select, iocp, epoll,kqueue及各种I/O复用机制
- easeljs web开发围住神经小猫咪【一】
- cocostudio scrollview裁切bug
- Android多机适配
- html 等待界面
- Java多线程操作
- 操作系统之分页式内存管理1
- Web前端引路灯
- 视觉测量与三维重建(二)
- MFC 自定义类的串行化使能方法
- Builder --- 的比喻理解
- 关灯游戏:UI3-2
- iptables 的原理
- 0/1背包问题的动态规划法