标签:des style blog http io color ar 使用 java
由于自己最近接手一个项目,构思过程中,线程可能会用的较多,所以今天翻出来把线程这块好好复习一下,以下是一点学习总结。分享写的比较拙略,只为自己笔记。为自己以后存储参考资源而已。
pass:(被重写的方法不能跑一个比父类更大的异常)
创建于一个继承thread的子类:
1 class testThread extends Thread{ 2 public void Run(){//新建一个线程里的run方法,实现此子线程需要完成的功能 3 for(int i = 0;i < 100;i++){ 4 Thread.currentThread().sleep(1000); 5 System.out.println(Thread.currentThread().getName()+":"+i); 6 } 7 } 8 } 9 public class TestThread{ 10 static void main(String arg[]){ 11 testThread sT1 = new testThread(); 12 testThread sT2 = new testThread();//创建一个子类的对象 13 sT1.setName("线程1:"); 14 sT1.setpriority(Thread.MAX.PRIORITY); 15 sT1.start(); 16 sT2.setName("线程2:"); 17 sT2.start(); 18 //调用线程的start方法,启动此线程,调用相应的run方法, 19 //一个线程只能执行一次start,具体请见jdk手册。 20 //如果此处启用的是run方法,则不是双线程。必须是start方法。 21 Thread.currentThread().setName("子线程:"); 22 for(int i = 0;i < 100;i++){ 23 System.out.println(Thread.currentThread().getName()+":"+Thread.currentThread().getPriority()+":"i); 24 /*if(i % 10 == 0){ 25 Thread.currentThread().yield(); 26 27 }*/ 28 /*if(i % 10 ==0){ 29 try{ 30 sT1.join(); 31 }catch(InterruptedException e){ 32 e.printStackTrace(); 33 } 34 }*/ 35 } 36 System.out.println(sT1.isAlive());/*返回FALSE*/ 37 } 38 }
Thread常用方法:
1.start() 启动线程并执行相应的run方法。
2.run() 子线程要执行的代码放入其中,一般都是被重写。
3.currentThread() 静态的,调取当前的线程
4.getName() 获取当前线程的名字
5.setName() 设置子线程的名字
6.yield() 线程释放当前cpu的执行权
7.join() 在a线程中调用b线程的join方法,表示,当执行到此方法,a线程停止,直至b线程全部结束,a线程才继续执行
8.isAlive() 判断当前线程是否还存活
9.sleep(long l) 显示的当前线程睡眠1毫秒
10.设置线程的优先级:getpriority() 返回线程优先级;setpriority(int newpriority)改变线程的优先级
1 /* 2 创建两个子线程,让其中一个输出1-100之间的偶数,另一个输出1-100之间的奇数 3 */ 4 class SubThread1 extends Thread{ 5 public void Run(){ 6 for (int i = 1; i < 100;i++){ 7 if(i % 2 == 0){ 8 System.out.println(Thread.currentThread().getName()+":"+i); 9 } 10 } 11 } 12 } 13 class SubThread2 extends Thread{ 14 public void Run(){ 15 for (int i = 1; i < 100;i++){ 16 if(i % 2 != 0){ 17 System.out.println(Thread.currentThread().getName()+":"+i); 18 } 19 } 20 } 21 } 22 public class TestThread{ 23 public static void main(String[] args) { 24 SubThread sT1 = new SubThread1(); 25 SubThread sT2 = new SubThread(); 26 //sT1.start(); 27 //sT2.start(); 28 //继承于Thread类的匿名对象 29 new Thread(){ 30 public void Run(){ 31 for (int i = 1; i < 100;i++){ 32 if(i % 2 != 0){ 33 System.out.println(Thread.currentThread().getName()+":"+i); 34 } 35 } 36 }}.start(); 37 new Thread(){ 38 public void Run(){ 39 for (int i = 1; i < 100;i++){ 40 if(i % 2 != 0){ 41 System.out.println(Thread.currentThread().getName()+":"+i); 42 } 43 } 44 }}.start(); 45 46 } 47 }
1 /*模拟火车站首售票窗口,开启三个窗口售票.总票数为100张*/ 2 class Window extends Thread{ 3 static int tickets = 100;//声明为固定变量实现公用,限制只有一百张,但声明周期很长 4 public void Run(){ 5 while(true){ 6 if(tickets > 0){ 7 System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--); 8 }else{ 9 break;//退出 10 } 11 } 12 } 13 } 14 public class TestWindow{ 15 16 } 17 18 public static void main(String[] args) { 19 Window W1 = new Window(); 20 Window W2 = new Window(); 21 Window W3 = new Window(); 22 23 W1.setName("窗口1:"); 24 W2.setName("窗口2:"); 25 W3.setName("窗口3:"); 26 27 W1.start(); 28 W2.start(); 29 w3.start(); 30 }
第二种方式-实现:
//1.创建一个实现了runable的类 class PrintNum1 implements Runable{ public void run(){//实现接口的抽象方法 for (int i = 1; i < 100;i++){ if(i % 2 != 0){ System.out.println(Thread.currentThread().getName()+":"+i); } } } } public class TestWindow1{ public static void main(String[] args) { //2.创建一个runable接口的实现对象 PrintNum1 p = new PrintNum1(); //要想启动一个多线程,必须调用start方法 //3.将此对象作为形参传递给Thread类的构造器中,创建Thread类的对象,此对象即为一个线程。 Thread T1 = new Thread(p);//构造一个Thread对象 T1.start(); //启动线程,执行Thread对象生成时构造器形参的对象的Run方法 //4.在创建一个线程 Thread T2 = new Thread(p);//构造一个Thread对象 T2.start(); } }
实现的方式实现多窗口售票 存在线程的安全问题
为何会出现程序的安全问题?
由于一个线程在操作共享数据的执行过程中未执行完的情况下,另外的线程参与进来,导致共享数据存在安全问题
如何解决?
必须让一个操作共享数据完毕之后,其他线程才有机会共享数据的操作。
java如何实现线程安全?
线程的同步:1.同步代码块 synchronized(同步监视器){
需要同步的代码块(操作数据共享的代码)
}
共享数据:多个线程共同操作的一个数据
同步监视器:由任何一个类的对象来充当,那个线程获取此监视器,谁就执行大括号里面的代码 俗称:锁
在实现的方式中考虑同步的话可以考虑this来充当锁,但在继承当中需要慎重.
1 class Window1 implements Thread{ 2 int ticket = 100;//共享数据 3 static Object object = new Object(); 4 public void run(){ 5 //Object object = new Object();不能在此处写,这样会导致引发三次局部变量 6 while(true){ 7 synchronized(object){//此处可以为this,代表当前的对象W1 8 if(tickets > 0){ 9 try{//这个地方会出现重票和错票 10 11 Thread.currentThread().sleep(10);//让其休眠10毫秒 12 }catch(InterruptedException e){ 13 e.printStackTrace(); 14 } 15 System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--); 16 }else{ 17 break;//退出 18 } 19 } 20 } 21 } 22 } 23 public class TestWindow1{ 24 public static void main(String[] args) { 25 Window1 W1 = new Window1(); 26 Thread t1 = new Thread(W1); 27 Thread t2 = new Thread(W1); 28 /*只new了一个w对象,三个线程共享*/ 29 t1.setName("窗口1:"); 30 t2.setName("窗口2:"); 31 32 t1.start(); 33 //共享同一个W对像 34 35 t2.start(); 36 37 } 38 39 }
1 /*实现改进版售票器*/ 2 class Window1 implements Thread{ 3 int ticket = 100; 4 public void run(){ 5 while(true){ 6 if(tickets > 0){ 7 /*try{//这个地方会出现重票和错票 8 9 Thread.currentThread().sleep(10);//让其休眠10毫秒 10 }catch(InterruptedException e){ 11 e.printStackTrace(); 12 }*/ 13 System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--); 14 }else{ 15 break;//退出 16 } 17 } 18 } 19 } 20 public class TestWindow1{ 21 public static void main(String[] args) { 22 Window1 W1 = new Window1(); 23 Thread t1 = new Thread(W1); 24 Thread t2 = new Thread(W1); 25 /*只new了一个w对象,三个线程共享*/ 26 t1.setName("窗口1:"); 27 t2.setName("窗口2:"); 28 29 t1.start(); 30 //共享同一个W对像 31 32 t2.start(); 33 34 }
同步方法
将操作共享数据的方法声明为synchronized,
即此方法为同步方法,能够保证当其中一个线程执行此方法时,
其他线程在外等待直到此线程执行完此方法
>同步方法的锁是当前对象:this
线程的弊端:同一个时间只有一个线程访问共享数据,效率变低了。
1 /*实现改进版售票器*/ 2 class Window1 implements Thread{ 3 int ticket = 100; 4 public void run(){ 5 while(true){ 6 show(); 7 8 } 9 } 10 public synchronized void show(){ 11 12 if(tickets > 0){ 13 try{//这个地方会出现重票和错票 14 Thread.currentThread().sleep(10);//让其休眠10毫秒 15 }catch(InterruptedException e){ 16 e.printStackTrace(); 17 } 18 System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--); 19 }else{ 20 break;//退出 21 22 } 23 } 24 } 25 public class TestWindow1{ 26 public static void main(String[] args) { 27 Window1 W1 = new Window1(); 28 Thread t1 = new Thread(W1); 29 Thread t2 = new Thread(W1); 30 /*只new了一个w对象,三个线程共享*/ 31 t1.setName("窗口1:"); 32 t2.setName("窗口2:"); 33 34 t1.start(); 35 //共享同一个W对像 36 37 t2.start(); 38 39 }
1 /*继承实现同步方法*/ 2 class Window extends Thread{ 3 static int tickets = 100;//声明为固定变量实现公用,限制只有一百张,但声明周期很长 4 static Object o = new Object(); 5 public void Run(){ 6 while(true){ 7 synchronized(o){ 8 if(tickets > 0){ 9 System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--); 10 }else{ 11 break;//退出 12 } 13 } 14 } 15 } 16 } 17 public class TestWindow{ 18 public static void main(String[] args) { 19 Window W1 = new Window(); 20 Window W2 = new Window(); 21 Window W3 = new Window(); 22 23 W1.setName("窗口1:"); 24 W2.setName("窗口2:"); 25 W3.setName("窗口3:"); 26 27 W1.start(); 28 W2.start(); 29 w3.start(); 30 } 31 }
/*懒汉模式-单例模式 sleep()和yield()不会释放锁的, static方法里面锁不能写this,使用当前类本身充当*/ class Singleton{ private Singleton(){ } private static Singleton instance = null; public static Singleton getInstance(){ if(instance == null){ synchronized(Singleton.class){ if(instance == null){ instance = new Singleton(); } } } return instance; } } public class TestSingleton{ public static void main(String[] args) { Singleton s1 = new Singleton.getInstance(); Singleton s2 = new Singleton.getInstance(); System.out.println(s1 == s2);//判断两个对象相等,只能用== } }
1 /*银行存钱问题 2 */ 3 class Count{ 4 double balance;//余额 5 public Account(){ 6 7 } 8 public synchronized void despoit(double amt){//存钱 9 notify();//实现二者交替打印 10 balance += amt; 11 try{ 12 Thread.currentThread().sleep(10); 13 } 14 catch(InterruptedException e){ 15 e.printStackTrace(); 16 } 17 System.out.println(Thread.currentThread().getName()+":"+balance); 18 wait(); 19 } 20 21 } 22 class Customer extends Thread{ 23 Account account; 24 public Customer(Account account){ 25 this.account = account; 26 } 27 public void run(){ 28 for(int i = 0;i<3;i++){ 29 account.despoit(1000); 30 } 31 } 32 } 33 public class TestAccount{ 34 public static void main(String[] args) { 35 Account acct =new Account(); 36 Customer c1 = new Customer(acct); 37 Customer c2 = new Customer(acct); 38 Customer c3 = new Customer(acct); 39 40 c1.setName("1"); 41 c2.setName("2"); 42 c3.setName("3"); 43 44 c1.start(); 45 c2.start(); 46 c3.start(); 47 } 48 }
1 /*死锁问题--处理线程同步时容易出现 2 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的资源,就形成了线程的死锁*/ 3 public class TestDeadLock{ 4 static StringBuffer sb1 = new StringBuffer(); 5 static StringBuffer sb2 = new StringBuffer(); 6 7 public static void main(String[] args) { 8 new Thread(){ 9 public void run(){ 10 synchronized(sb1){ 11 try{ 12 Thread.currentThread().sleep(10); 13 } 14 catch(InterruptedException e){ 15 e.printStackTrace(); 16 } 17 sb1.append("A"); 18 synchronized(sb2){ 19 sb2.append("B"); 20 System.out.println(sb1); 21 System.out.println(sb2); 22 } 23 } 24 } 25 }.start(); 26 27 new Thread(){ 28 public void run(){ 29 synchronized(sb1){ 30 try{ 31 Thread.currentThread().sleep(10); 32 } 33 catch(InterruptedException e){ 34 e.printStackTrace(); 35 } 36 sb1.append("C"); 37 synchronized(sb2){ 38 sb2.append("D"); 39 System.out.println(sb1); 40 System.out.println(sb2); 41 } 42 } 43 } 44 }.start(); 45 } 46 }
/*Deadlock.java*/ class A{ public synchronized void foo(B b){ System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入了A实例的foo方法"); try{ Thread.sleep(200) }catch(InterruptedException e){ e.printStackTrace(); } System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用b的last方法"); } public synchronized void Last(){ System.out.println("进入了A的last方发出内部"); } } class B{ public synchronized void bar(A a){ System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入了B实例的bar方法");try{ Thread.sleep(200) }catch(InterruptedException e){ e.printStackTrace(); } System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用A的last方法"); } public synchronized void Last(){ System.out.println("进入了B的last方发出内部"); } } public class Deadlock implements Runable{ A a = new A(); B b = new B(); public void init(){ Thread.currentThread.setName("主线程"); //调用a对象的foo方法 a.foo(b); System.out.println("进入了主线程之后"); } public void run(){ Thread.currentThread.setName("副线程"); //调用b对象的bar方法 b.bar(a); System.out.println("进入了副线程之后"); } public static void main(String[] args) { Deadlock d1 = new Deadlock(); new Thread(d1).start();//启动run方法 d1.init(); } }
线程通信:
1.wait()方法:令当前线程挂起并放弃CPU,同步资源,使别的线程可访问并修改资源,而当前线程排队等候再次对资源的访问
2.notify()方法:唤醒正在排队等待同步资源的线程中优先级最高的
3.notifyAll()方法:唤醒正在等待资源的所有线程结束等待
java.lang.Object提供的这三个方法只有在synchronized方法中或synchronized代码块中才能使用,否则会报错
线程通信:
1 打印1-100,线程1,线程2交替打印*/ 2 class PrintNum implements Runable{ 3 int num = 1; 4 public void run(){ 5 6 while(true){ 7 synchronized(this){ 8 notify(); 9 if(num<100){ 10 try{Thread.currentThread().sleep(10); 11 }catch(InterruptedException e){ 12 e.printStackTrace(); 13 } 14 System.out.println(Thread.currentThread().getName()+":"+num); 15 num++; 16 }else{ 17 break; 18 } 19 wait(); 20 } 21 } 22 } 23 } 24 25 public class TestCommunication{ 26 public static void main(String[] args) { 27 PrintNum p = new PrintNum(); 28 Thread t1 = new Thread(p); 29 Thread t2 = new Thread(p); 30 31 t1.setName("甲"); 32 t1.setName("乙"); 33 34 t1.start(); 35 t2.start(); 36 } 37 38 }
生产者、消费者问题
多线程:消费者/生产者
共享数据:产品数量
1 class Clerk{//店员 2 int product; 3 4 public synchronized void addProduct(){//生产产品 5 if(product >= 20){ 6 wait(); 7 }else{ 8 product++; 9 System.out.println(Thread.currentThread().getName()+":生产了第"+ product +"个"); 10 notifyall(); 11 } 12 13 } 14 public synchronized void consumeProduct(){//消费产品 15 if(product <= 0){ 16 wait(); 17 }else{ 18 System.out.println(Thread.currentThread().getName()+"消费了第"+product +"个"); 19 product--; 20 notifyall(); 21 } 22 } 23 } 24 class Producer implements Thread{//生产者 25 Clerk clerk; 26 27 public Producer(Clerk clerk){ 28 this.clerk = clerk; 29 } 30 public void run(){ 31 System.out.println("生产者开始生产产品。"); 32 while(true){ 33 try{ 34 Thread.currentThread().sleep(10); 35 }catch(InterruptedException e) 36 { 37 e.printStackTrace(); 38 } 39 clerk.addProduct(); 40 } 41 } 42 43 } 44 class Consumer implements Runable{//消费者 45 Clerk clerk; 46 public Consumer(Clerk clerk){ 47 this.clerk = clerk; 48 } 49 public void run(){ 50 System.out.println("消费者开始消费产品。"); 51 while(true){ 52 try{ 53 Thread.currentThread().sleep(10); 54 }catch(InterruptedException e) 55 { 56 e.printStackTrace(); 57 } 58 clerk.consumeProduct(); 59 } 60 } 61 }
标签:des style blog http io color ar 使用 java
原文地址:http://www.cnblogs.com/Terminaling/p/4072359.html