Java学习 之 多线程(线程安全、同步、死锁、Lock锁、等待唤醒机制)
1 /* 2 3 线程安全:如果有多个线程在同时运行,而这些线程可能会同时运行这段代码,程序每次运行结果和单线程运行的结果是一样的, 4 5 而且其他的变量的值也和预期的是一样的,就是线程安全的 6 7 线程安全是由全局变量及静态变量引起的,若每个线程中对全局变量、静态变量只有读操作,而无写操作,这个全局变量是线程安全的; 8 9 若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全 10 11 */ 12 13 public class ThreadDemo{ 14 15 public static void main(String[] args){ 16 17 //创建票对象 18 19 Ticket t = new Ticket(); 20 21 //创建3个窗口 22 23 Thread t1 = new Thread(t , "窗口1"); 24 25 Thread t2 = new Thhread(t , "窗口2"); 26 27 Thread t3 = new Thhread(t , "窗口3"); 28 t1.start(); 29 30 t2.start(); 31 32 t3.start(); 33 34 } 35 36 } 37 38 public class Ticket implements Runnable{ 39 40 int ticket = 10; 41 42 public void run(){ 43 44 //模拟卖票 45 46 while(true){ 47 48 if(ticket > 0){ 49 50 //模拟选坐的操作 51 52 try{ 53 54 Thread.sleep(2000); 55 56 }catch(Exception e){ 57 58 e.printStackTrace(); 59 60 } 61 62 System.out.println("正在售票:" + ticket--); 63 64 } 65 66 } 67 68 } 69 70 } 71 72 /* 73 74 线程同步:Java中提供了线程同步机制,能够解决线程安全问题 75 76 方式: 77 78 1、同步代码块 79 80 synchronized(锁对象){可能产生线程安全问题的代码} 81 82 锁对象可以是任意对象,但多个线程时,要使用同一个锁对象才能够保证线程安全 83 84 2、同步方法 85 86 public synchronized void method(){可能产生线程安全问题的代码} 87 锁对象是this 88 89 3、静态同步方法 90 91 public static synchronized void method(){可能产生线程安全问题的代码} 92 锁对象是类名.class 93 94 */ 95 96 public class Ticket implements Runnable{ 97 98 int ticket = 10; 99 100 //定义锁对象 101 102 Object lock = new Object(); 103 104 public void run(){ 105 106 //模拟卖票 107 108 while(true){ 109 110 //同步代码块 111 112 synchronized(lock){ 113 if(ticket > 0){ 114 115 //模拟选坐的操作 116 117 try{ 118 119 Thread.sleep(2000); 120 121 }catch(Exception e){ 122 123 e.printStackTrace(); 124 125 } 126 127 System.out.println("正在售票:" + ticket--); 128 129 } 130 131 } 132 133 } 134 135 } 136 137 } 138 139 140 141 public class Ticket implements Runnable{ 142 143 int ticket = 10; 144 145 //定义锁对象 146 147 Object lock = new Object(); 148 149 public void run(){ 150 151 //模拟卖票 152 153 while(true){ 154 155 //同步方法 156 157 method(); 158 159 } 160 161 } 162 163 public synchronized void method(){ 164 165 if(ticket > 0){ 166 167 //模拟选坐的操作 168 169 try{ 170 171 Thread.sleep(2000); 172 173 }catch(Exception e){ 174 175 e.printStackTrace(); 176 177 } 178 179 System.out.println("正在售票:" + ticket--); 180 181 } 182 183 } 184 185 } 186 187 /* 188 189 死锁:当线程任务中出现了多个同步(多个锁时,如果同步中嵌套了其他同步,这时容易引发一种现象:程序出现无限等待,这种现象称为死锁) 190 191 synchronized(A锁){ 192 193 synchronized(B锁){ 194 195 } 196 } 197 198 */ 199 200 //定义锁对象类 201 202 public class MyLock{ 203 204 public static final Object locka = new Object(); 205 206 public static final Object lockb = new Object(); 207 } 208 209 public class ThreadTask implements Runnable{ 210 211 int x = new Random().nextInt(1); 212 213 //指定线程要执行的任务代码 214 215 public void run(){ 216 217 while(true){ 218 219 if(x % 2 == 0){ 220 221 synchronized(MyLock.locka){ 222 223 System.out.println("if-locka"); 224 225 synchronized(MyLock.lockb){ 226 227 System.out.println("if-lockb"); 228 229 } 230 } 231 }else{ 232 233 synchronized(MyLock.lockb){ 234 235 System.out.println("else-lockb"); 236 237 synchronized(MyLock.locka){ 238 239 System.out.println("else-locka"); 240 } 241 } 242 } 243 244 } 245 246 } 247 248 } 249 250 /* 251 252 Lock类: 253 254 void lock():获取锁 255 256 void unlock():释放锁 257 258 */ 259 260 public class Ticket implements Runnable{ 261 262 int ticket = 10; 263 264 //定义Lock锁对象 265 266 Lock lock = new ReentrantLoak(); 267 268 public void run(){ 269 270 //模拟卖票 271 272 while(true){ 273 274 lock.lock(); 275 276 if(ticket > 0){ 277 278 //模拟选坐的操作 279 280 try{ 281 282 Thread.sleep(2000); 283 284 }catch(Exception e){ 285 286 e.printStackTrace(); 287 288 } 289 290 System.out.println("正在售票:" + ticket--); 291 292 } 293 294 lock.unlock(); 295 296 } 297 298 } 299 300 } 301 302 } 303 304 /* 305 306 等待唤醒机制:让线程池中的线程具备执行功能 307 308 void wait():等待,将正在执行的线程释放其执行资格和执行权,并存储到线程池中 309 310 void notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且时任意的 311 312 void notifyAll():唤醒全部,可以将线程池中的所有wait()线程唤醒 313 314 */