在一个操作系统中,每个独立执行的程序都可以称为一个进程,也就是“正在运行的程 序”。而在进程中还可以有多个执行单元同时执行,这些执行单元可以看作程序执行的一条 条线索,被称为线程。Java 运行环境是一个包含了不同的类和程序的单一进程。线程可以被 称为轻量级进程。线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源。
二、线程的创建
1 public class Example02 { 2 public static void main(String[] args) { 3 MyThread myThread = new MyThread();//创建线程MyThread的线程对象 4 myThread.start();//开启线程 5 while (true){ //通过死循环语句打印输出 6 System.out.println("main()方法在运行"); 7 } 8 } 9 } 10 class MyThread extends Thread{ 11 public void run(){ 12 while (true){ 13 System.out.println("MyThread 类的run()方法"); 14 } 15 } 16 }
1 public class Example03 { 2 public static void main(String[] args) { 3 MyThread myThread = new MyThread();//创建线程MyThread的线程对象 4 Thread thread = new Thread(myThread);//创建线程对象 5 thread.start();//开启线程,执行线程中的run()方法 6 while (true){ //通过死循环语句打印输出 7 System.out.println("main()方法在运行"); 8 } 9 } 10 } 11 class MyThread implements Runnable{ 12 public void run(){ //线程的代码段,当调用start()方法时,线程从此处开始 13 while (true){ 14 System.out.println("MyThread 类的run()方法"); 15 } 16 } 17 }

1 public class Example08 { 2 public static void main(String[] args) throws Exception{ 3 // 创建一个线程 4 new Thread(new SleepThread()).start(); 5 for (int i= 1;i<=10;i++){ 6 if (i==5){ 7 Thread.sleep(2000);//当前线程休眠2秒 8 } 9 System.out.println("主线程正在输出:"+i); 10 Thread.sleep(500);//当前线程休眠500毫秒 11 } 12 } 13 } 14 class SleepThread implements Runnable{ 15 @Override 16 public void run() { 17 for (int i= 1;i<=10;i++){ 18 if (i==3){ 19 try{ 20 Thread.sleep(2000); 21 }catch (InterruptedException e ){ 22 e.printStackTrace(); 23 } 24 } 25 System.out.println("线程一正在输出:"+i); 26 try{ 27 Thread.sleep(500); 28 } catch (Exception e ){ 29 e.printStackTrace(); 30 } 31 } 32
1 //定义YieldThread类继承Thread类 2 class YieldThread extends Thread{ 3 // 定义一个有参构造方法 4 public YieldThread(String name){ 5 super(name);//调用父类的构造方法 6 } 7 8 @Override 9 public void run() { 10 for (int i= 0;i<5;i++){ 11 System.out.println(Thread.currentThread().getName()+"___"+i); 12 if (i==3){ 13 System.out.print("线程让步"); 14 Thread.yield();//线程运行至此,做出让步 15 } 16 } 17 } 18 } 19 public class Example09 { 20 public static void main(String[] args) { 21 //创建两个线程 22 Thread t1= new YieldThread("线程A"); 23 Thread t2= new YieldThread("线程B"); 24 //开启两个线程 25 t1.start(); 26 t2.start(); 27 } 28 29 }
1 public class Example10 { 2 public static void main(String[] args) throws Exception{ 3 // 创建线程 4 Thread t = new Thread(new EemergencyThread(),"线程一"); 5 t.start(); 6 for (int i=1;i<6;i++){ 7 System.out.println(Thread.currentThread().getName()+"输入:"+i); 8 if (i==2){ 9 t.join(); //调用join()方法 10 } 11 Thread.sleep(500); 12 } 13 } 14 } 15 class EemergencyThread implements Runnable{ 16 @Override 17 public void run() { 18 for (int i =1;i<6;i++){ 19 System.out.println(Thread.currentThread().getName()+"输入:"+i); 20 try{ 21 Thread.sleep(500); 22 }catch (InterruptedException e){ 23 e.printStackTrace(); 24 } 25 } 26 } 27 }
synchronized 返回值类型 方法名([参数1,......]){ }
1 //定义Ticket1类实现Runnable接口 2 class Ticket1 implements Runnable{ 3 private int tickets=10; //定义变量tickets,并赋值10 4 /* 同步代码块用法 5 Object lock = new Object();//定义任意一个对象,用做同步代码块的锁 6 public void run(){ 7 while (true){ 8 synchronized(lock){ 9 try { 10 Thread.sleep(10); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 if(tickets>0){ 15 System.out.println(Thread.currentThread().getName() 16 + "---卖出的票" + tickets--); 17 }else{ 18 break; 19 } 20 } 21 } 22 23 }*/ 24 25 public void run(){ 26 while (true){ 27 saleTicket(); //调用售票方法 28 if (tickets<=0){ 29 break; 30 } 31 } 32 33 } 34 //定义一个同步方法saleTicket() 35 private synchronized void saleTicket (){ 36 if (tickets>0) { 37 try { 38 Thread.sleep(10); 39 } catch (InterruptedException e) { 40 e.printStackTrace(); 41 } 42 System.out.println(Thread.currentThread().getName() + 43 "---卖出的票" + tickets--); 44 } 45 } 46 } 47 public class Example12 { 48 public static void main(String[] args) { 49 Ticket1 ticket =new Ticket1(); 50 new Thread(ticket,"线程1").start(); 51 new Thread(ticket,"线程2").start(); 52 new Thread(ticket,"线程4").start(); 53 new Thread(ticket,"线程3").start(); 54 } 55 }
死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
java 死锁产生的四个必要条件:
①互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
②不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
③请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
④循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
方法声明 | 功能描述 |
void wait() | 使当前线程放弃同步锁并进入等待,直到其他线程进入此同步锁,并调用notify()方法或notifyAll()方法唤醒该线程为止 |
void notify() | 唤醒此同步锁上等待的第一个调用wait()方法的线程 |
void notifyAll() | 唤醒此同步锁上调用wait()方法的所有线程 |
1 class Storage{ 2 private int[] cells =new int[10];// 数组存储数组 3 private int inPos,outPos;// inPos表示存入时数组下标,outPos表示取出时数组下标 4 private int count;//存入或取出数据的数量 5 public synchronized void put(int num){ //定义一个put()方法向数组中存入数据 6 try { 7 //如果放入数据等于cells的长度,此线程等待 8 while (count == cells.length) { 9 this.wait(); 10 } 11 cells[inPos] = num;//向数组中放入数据 12 System.out.println("cells[" + inPos + "]中放入数据---" + cells[inPos]); 13 inPos++;//存完元素让位置加1 14 if (inPos == cells.length) 15 inPos = 0;//当inPos为数组长度是10,将其置为0 16 count++; 17 this.notify(); 18 }catch (Exception e){ 19 e.printStackTrace(); 20 } 21 } 22 //定义一个get()方法从数组中取出数据 23 public synchronized void get(){ 24 try{ 25 while (count==0){ 26 this.wait(); 27 } 28 int data=cells[outPos]; 29 System.out.println("从cells["+outPos+"]中取出数据"+data); 30 cells[outPos]=0;//取出后,当前数据置零 31 outPos++; //取完元素后让位置加1 32 if (outPos==cells.length) 33 outPos=0; 34 count--;//每取出一个元素count减1 35 this.notify(); 36 }catch (Exception e){ 37 e.printStackTrace(); 38 } 39 } 40 } 41 class Input implements Runnable{ //输入线程类 42 private Storage st; 43 private int num; //定义一个变量num 44 Input(Storage st){ //通过构造方法接收一个Storage对象 45 this.st=st; 46 } 47 public void run(){ 48 while (true){ 49 st.put(num++);//将num存入数组,每次存入后num自增 50 } 51 } 52 } 53 class Output implements Runnable{ //输出线程类 54 private Storage st; 55 Output(Storage st){ //通过构造方法接收一个Storage对象 56 this.st=st; 57 } 58 public void run(){ 59 while (true){ 60 st.get();//循环取出元素 61 } 62 } 63 } 64 public class Example17 { 65 public static void main(String[] args) { 66 Storage st=new Storage();//创建数组存储类对象 67 Input input=new Input(st);//创建Input对象传入Storage对象 68 Output output=new Output(st);//创建Output对象传入Storage对象 69 new Thread(input).start();//开启新线程 70 new Thread(output).start();//开启新线程 71 72 } 73 }
运行结果
cells[1]中放入数据---214311 cells[2]中放入数据---214312 cells[3]中放入数据---214313 cells[4]中放入数据---214314 cells[5]中放入数据---214315 cells[6]中放入数据---214316 cells[7]中放入数据---214317 cells[8]中放入数据---214318 cells[9]中放入数据---214319 cells[0]中放入数据---214320 从cells[1]中取出数据214311 从cells[2]中取出数据214312 从cells[3]中取出数据214313 从cells[4]中取出数据214314 从cells[5]中取出数据214315 从cells[6]中取出数据214316 从cells[7]中取出数据214317 从cells[8]中取出数据214318 从cells[9]中取出数据214319 从cells[0]中取出数据214320
多线程累加例子:
模拟10个线程,第一个线程从1加到10,第二个线程从11加到20.....第十个线程从91加到100,最后在把10个线程结果相加。
1 public class Accumulator extends Thread { 2 private int stratNum; 3 public static int sum; 4 public Accumulator(int startNum) { 5 this.stratNum = startNum; 6 } 7 public static synchronized void add(int num) { 8 sum += num; 9 } 10 public void run() { 11 int sum = 0; 12 for (int i = 0; i < 10; i++) { 13 sum += stratNum + i; 14 } 15 add(sum); 16 } 17 public static void main(String[] args) throws Exception { 18 Thread[] threadList = new Thread[10]; 19 for (int i = 0; i < 10; i++) { 20 threadList[i] = new Accumulator(10 * i + 1); 21 threadList[i].start(); 22 } 23 for (int i = 0; i < 10; i++) { 24 threadList[i].join(); 25 } 26 System.out.println("Sum is : " + sum); 27 } 28 }