Java多线程的使用
来源:互联网 发布:电商运营数据分析维度 编辑:程序博客网 时间:2024/05/21 22:35
1. 在java里如何创建多线程
如何创建多线程?
答:java创建多线程有两种方式,可以同实现 Runnable
接口,或者继承 Thread
类。
如下面示例:
package com.tenchael.forjob;public class Demo { public static void main(String[] args) { new Thread(new A()).start(); new Thread(new B()).start(); }}class A implements Runnable { public void run() { try { Thread.currentThread().sleep(1000); System.out.println("Thread A"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}class B extends Thread { @Override public void run() { System.out.println("Thread B"); }}
类A
实现 Runnable
接口,要实现run()
方法;类B
继承自Thread
,重写了run()
方法。程序是顺序执行的,若按单线程,会先打印Thread A
再打印Thread B
,但由于采用了多线程,A
类实例在run()
方法内休眠了1000ms,结果是先打印Thread B
。
2. 多线程状态
JAVA中线程有哪些状态?如何切换?
答:Java中线程有新建
、运行
、就绪
、休眠
和终止
五个状态,这五个状态的含义分别是指:
状态间如下图所示:
3. 资源竞争
如何做到同步?
答:Java里采用synchronized
关键字,既可以修饰代码块,也能作用在资源上。下面用一个实例说明其用法。
下面程序有三个类,CallMe、Caller、SyncDemo。SyncDemo中创建CallMe资源;CallMe里有call()方法,call方法在打印消息的时候中途会被要求休眠1s钟;Caller里有CallMe作为调用target。
package com.tenchael.jobinterview;public class SyncDemo { public static void main(String[] args) { CallMe target = new CallMe(); new Caller(target, "Hello"); new Caller(target, "Synchronized"); new Caller(target, "World"); }}class CallMe { void call(String msg) { System.out.print("["); System.out.print(msg); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("]"); }}class Caller implements Runnable { String msg; CallMe target; Thread t; Caller(CallMe target, String msg) { this.target = target; this.msg = msg; t = new Thread(this, msg); t.start(); } public void run() { target.call(msg); }}
打印结果:
[Hello[World[Synchronized]]]
可以看到输出的结果异常,字符串乱序,这主要是由于,线程在执行了System.out.print(msg);
后被中断,切换到其他的线程,最后在切换回来时,中途打印了其它线程的内容。
为了保证只有一个线程使用call方法,Java中可以对方法使用synchronized
修饰,实现访问的序列化。
package com.tenchael.jobinterview;public class SyncDemo { public static void main(String[] args) { CallMe target = new CallMe(); new Caller(target, "Hello"); new Caller(target, "Synchronized"); new Caller(target, "World"); }}class CallMe { synchronized void call(String msg) { System.out.print("["); System.out.print(msg); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("]"); }}class Caller implements Runnable { String msg; CallMe target; Thread t; Caller(CallMe target, String msg) { this.target = target; this.msg = msg; t = new Thread(this, msg); t.start(); } public void run() { target.call(msg); }}
打印结果:
[Hello][World][Synchronized]
在类中创建synchronized
方法是一种简单的有效的解决同步的方式,然而,它并不是在所有情况下都有效果。考虑下面场景:假设你希望同步访问没有设计为多线程访问的类的对象,也就是说类中你希望同步访问的资源没有使用synchronized
,更普遍的情况,很多第三方的类库这是提供编译打包好的形式给你使用,你怎样才能使其同步访问呢?
Java中解决这个问题的方式是,对将该类的方法置于一个synchronized
的代码块中,代码块的一般形式是:
synchronized (object) { //需要同步访问的方法}
其含义是:
进入
synchronized
修饰的这段代码内的线程必须先去获取一个特定对象的锁定标示,并且虚拟机保证这个标示一次只能被一条线程拥有。
下面是后一种替代方案:
package com.tenchael.jobinterview;public class SyncDemo { public static void main(String[] args) { CallMe target = new CallMe(); new Caller(target, "Hello"); new Caller(target, "Synchronized"); new Caller(target, "World"); }}class CallMe { void call(String msg) { System.out.print("["); System.out.print(msg); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("]"); }}class Caller implements Runnable { String msg; CallMe target; Thread t; Caller(CallMe target, String msg) { this.target = target; this.msg = msg; t = new Thread(this, msg); t.start(); } public void run() { synchronized (target) { target.call(msg); } }}
要注意的是,上面代码,target.call(msg);
语句块在被synchronized
修饰时,并不要求括号里的对象是target
,只要不同线程在互斥访问使用的是同一个对象,都能起到同步作用。如上面的代码也可写为:
package com.tenchael.jobinterview;public class SyncDemo { public static void main(String[] args) { Object lock = new Object();// 同步锁 CallMe target = new CallMe(); new Caller(target, "Hello", lock); new Caller(target, "Synchronized", lock); new Caller(target, "World", lock); }}class CallMe { void call(String msg) { System.out.print("["); System.out.print(msg); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("]"); }}class Caller implements Runnable { String msg; CallMe target; Thread t; Object lock; Caller(CallMe target, String msg, Object lock) { this.target = target; this.msg = msg; this.lock = lock; t = new Thread(this, msg); t.start(); } public void run() { synchronized (lock) { target.call(msg); } }}
- java多线程的使用
- Java多线程的使用
- Java多线程的使用
- Java多线程的使用
- Java多线程的使用
- JAVA---多线程的使用
- Java多线程的使用
- java多线程的使用
- java多线程的使用
- java多线程的使用
- Java -- 多线程的使用
- JAVA多线程的使用
- java多线程的使用
- Lock的使用 java多线程
- java多线程 join的使用
- JAVA实验 多线程的使用
- Java(多线程的使用)
- Java中多线程的使用
- 渠道系统和 OA系统待办事项接口
- [设计]字象乾坤之字体的性格
- linux mmap出现Address 0x7ffff7ff6000 out of bounds>
- 进程kswapd0与events/0消耗大量CPU的问题
- pragma comment的使用(转)
- Java多线程的使用
- DevExtreme常用示例:如何在Visual Studio中创建本地封装包
- iOS开发——为什么我的scanForPeripheralsWithServices根本不起作用
- linux之cut用法
- [java] parse() valueOf() toString的区别
- 关于数据库字段长度字节(byte)和(bit)的几个概念问题!
- CnPack实用功能推荐
- Android批量图片加载经典系列——afinal框架实现图片的异步缓存加载
- jquery 中post 、get的同步问题