Java传统线程创建方式和互斥
2017-05-17 22:06
357 查看
* 多线程并不会提高执行效率,性能更低
* 多线程会抢占cpu的资源,会占用更多的服务器带宽,这样看起来就感觉会更快
创建线程有两种方式:一种是创建Thread的子类,覆盖Thread的run方法,还有一种是构造器传入Runnable对象,使用Runnable对象的run方法:
线程的互斥:使用sychronized关键字
线程同步通信的例子:
main本身就是是一个线程
/**
* 题目:子线程循环10次,接着主线程循环5次,接着又回到子线程循环10次,主线程循环100次,
* 如此循环50次
*
*/
public class Test {
public static void main(String[] args) {
Business business = new Business();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<50; i++){
business.sub(i);
}
}
}).start();
for(int i= 0 ; i< 50 ; i++){
business.main(i);
}
}
static class Business{
boolean shouldSub = true;
public synchronized void sub(int i){
while(!shouldSub){ //使用while而不是if防止偽喚醒
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=0; j<10; j++){
System.out.println("thread1 : " + j + "/" + i);
}
shouldSub = false;
this.notify();
}
public synchronized void main(int i){
while(shouldSub){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=0; j<5; j++){
System.out.println("thread2 : " + j + "/"+ i);
}
shouldSub = true;
this.notify();
}
}
}
* 多线程会抢占cpu的资源,会占用更多的服务器带宽,这样看起来就感觉会更快
创建线程有两种方式:一种是创建Thread的子类,覆盖Thread的run方法,还有一种是构造器传入Runnable对象,使用Runnable对象的run方法:
public class TraditionlThread { /** * 创建线程的两种方式 * @param args */ public static void main(String[] args) { //方式一: 创建Thread的子类,覆盖Thread的run方法 Thread thread = new Thread(){ @Override public void run() { while(true){ try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()); } } }; thread.start(); // 源码里边是Runnable对象不为null就执行Runnable的run方法 // 方式二:构造函数中传入Runnable对象 Thread thread2 = new Thread(new Runnable() { @Override public void run() { while(true){ try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()); } } }); thread2.start(); /* * 两种方式的区别: * 第二种方式更加体现面向对象的方式 * * */ // 同时有子类的run方法和Runnable对象,那么程序会执行子类的run方法,子类的方法会覆盖父类的 new Thread(new Runnable() { @Override public void run() { while(true){ try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } System.out.println("runnable Thread:" + Thread.currentThread().getName()); } } }){ public void run() { while(true){ try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } System.out.println("子类 Thread:" + Thread.currentThread().getName()); } }; }.start(); } }
线程的互斥:使用sychronized关键字
/** * 傳統線程互斥技術 * 線程安全問題可以用銀行轉賬來解釋 * @author admin */ public class TraditionalSychronized{ public static void main(String[] args) { OutputSafe2 out = new OutputSafe2(); write(out); } /** * 這樣寫會出現錯亂 */ static class Output{ public void output(String name){ for(int i=0; i<name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } } /** * 方式一: 同步代碼塊 * 調用此方法的鎖要為同一個對象 */ static class OutputSafe1{ public void output(String name){ synchronized(OutputSafe1.class){ // 鎖對象可以設置為當前類的字節碼對象 for(int i=0; i<name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } } } /** * 方式二:同步方法 * 方法裡邊的所有代碼都需要原子性 那麼用同步方法 * * 注意:如果給同步方法中寫同步代碼塊很容易發生死鎖現象 */ static class OutputSafe2{ public synchronized void output(String name){ for(int i=0; i<name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } } public static void write(OutputSafe2 out){ new Thread(new Runnable() { public void run() { while(true){ try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } out.output("abcdef"); } } }).start(); new Thread(new Runnable() { public void run() { while(true){ try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } out.output("uvwxyz"); } } }).start(); } }
线程同步通信的例子:
main本身就是是一个线程
/**
* 题目:子线程循环10次,接着主线程循环5次,接着又回到子线程循环10次,主线程循环100次,
* 如此循环50次
*
*/
public class Test {
public static void main(String[] args) {
Business business = new Business();
new Thread(new Runnable() {
@Override
public void run() {
for(int i=0; i<50; i++){
business.sub(i);
}
}
}).start();
for(int i= 0 ; i< 50 ; i++){
business.main(i);
}
}
static class Business{
boolean shouldSub = true;
public synchronized void sub(int i){
while(!shouldSub){ //使用while而不是if防止偽喚醒
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=0; j<10; j++){
System.out.println("thread1 : " + j + "/" + i);
}
shouldSub = false;
this.notify();
}
public synchronized void main(int i){
while(shouldSub){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j=0; j<5; j++){
System.out.println("thread2 : " + j + "/"+ i);
}
shouldSub = true;
this.notify();
}
}
}
相关文章推荐
- java多线程之创建线程的两种传统方式
- 【java并发】传统线程技术中创建线程的两种方式
- java多线程01:创建线程的两种传统方式
- 【java并发】传统线程技术中创建线程的两种方式
- 【java并发】传统线程技术中创建线程的两种方式
- Java并发01----传统线程中创建线程的两种方式
- java创建线程的两种传统方式
- 【java多线程与并发库】---传统java多线程<2> 线程创建方式
- 【java多线程与并发库】---传统java多线程<2> 线程创建方式
- java多线程总结一:线程的两种创建方式及优劣比较
- java创建线程的第二种方式:实现Runnable接口
- java多线程总结一: 线程的两种创建方式及优劣比较
- Java值创建线程的两种方式对比
- java创建线程的三种方式
- 创建线程的两种传统的方式
- Java【多线程知识总结(5)】比较继承Thread类创建线程和实现Runnable接口创建线程这两种方式
- Java线程的两种创建方式及优劣比较
- java中创建线程的的几种方式
- java中创建线程的两种方式