Java基础之线程

1.   线程

2.   Thread类创建线程:继承Thread类后重写run方法,在主函数中创建出该类后调用start方法启动线程

publicclass ThreadDemo1 {
   publicstaticvoid main(String[] args) {
      new TestThread().start();
      while(true){
         System.out.println("main():" + Thread.currentThread().getName());//打印出当前线程类的名称
      }
   }
 
}
class TestThread extends Thread{
   publicvoid run(){
      while(true){
         System.out.println("run():" + Thread.currentThread().getName());
      }
   }
}

3.   前台线程和后台线程:如果是前台线程比如上面的TestThread,则main主线程结束的时候,TestThread线程仍然在执行;如果是后台线程,则前台线程结束后,后台线程也会结束;如下:

publicclass ThreadDemo1 {
   publicstaticvoid main(String[] args) {
//    new TestThread().start();
      Thread aa = new TestThread();
      aa.setDaemon(true);
      aa.start();
      /*while(true){
         System.out.println("main():"+ Thread.currentThread().getName());//打印出当前线程类的名称
      }*/
   }
 
}
class TestThread extends Thread{
   publicvoid run(){
      while(true){
         System.out.println("run():" + Thread.currentThread().getName());
      }
   }
}

4.   联合线程:

publicclass ThreadDemo1 {
   publicstaticvoid main(String[] args) {
      // new TestThread().start();
      Thread aa = new TestThread();
      // aa.setDaemon(true);
      aa.start();
      int index = 0;
      while (true) {
         if (index++ == 200){
            try {
                aa.join();// 将aa线程合并到主线程中,之后aa线程在执行,主线程在等待;也可以在join方法中指定合并线程的时间
            } catch (InterruptedExceptione) {
                e.printStackTrace();
            }
         }
         System.out.println("main():" + Thread.currentThread().getName());// 打印出当前线程类的名称
      }
   }
 
}
 
class TestThread extends Thread {
   publicvoid run() {
      while (true) {
         System.out.println("run():" + Thread.currentThread().getName());
      }
   }
}

5.   利用runnable接口实现Thread

public class ThreadDemo1 {
   public static void main(String[] args) {
      // new TestThread().start();
      Thread aa = new Thread(newTestThread());
      // aa.setDaemon(true);
      aa.start();
      int index = 0;
      while (true) {
         if (index++ == 200){
            try {
                aa.join(1000);// 将aa线程合并到主线程中,之后aa线程在执行,主线程在等待;也可以在join方法中指定合并线程的时间
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
         }
         System.out.println("main():" + Thread.currentThread().getName());// 打印出当前线程类的名称
      }
   }
 
}
 
class TestThread implements Runnable {
   publicvoid run() {
      while (true) {
         System.out.println("run():" + Thread.currentThread().getName());
      }
   }
}

6.   使用runnable接口实现的线程比继承Thread类实现的线程灵活得多:

public class ThreadDemo1 {
	public static void main(String[] args) {
		// new TestThread().start();
		Thread aa = new TestThread();
		// aa.setDaemon(true);
		aa.start();
		aa.start();
		aa.start();

	}

}

class TestThread extends Thread {
	int tickets = 100;

	public void run() {
		while (true) {
			if(tickets > 0)
			System.out.println("run():" + Thread.currentThread().getName()
					+ "is saling ticket" + tickets--);
		}
	}
}

上面的代码中只是启动了一个线程;

public class ThreadDemo1 {
   public static void main(String[] args) {
      // new TestThread().start();
      TestThread aa = new TestThread();
      // aa.setDaemon(true);
      new Thread(aa).start();
      new Thread(aa).start();
      new Thread(aa).start();
      new Thread(aa).start();
   }
 
}
 
class TestThreadimplements Runnable {
   inttickets = 100;
 
   publicvoid run() {
      while (true) {
         if(tickets > 0)
         System.out.println("run():" + Thread.currentThread().getName()
                + "is saling ticket" + tickets--);
      }
   }
}

7.   使用runnable接口可以实现几块代码同时处理相同的资源,所以这种用法使用比较多;

8.   多线程的应用:网络聊天程序,将发信息和接受信息放置到两个线程中执行;

9.   多线程的同步问题:问题的出现

public class ThreadDemo1 {
   public static void main(String[] args) {
      // new TestThread().start();
      TestThread aa = new TestThread();
      // aa.setDaemon(true);
      new Thread(aa).start();
      new Thread(aa).start();
      new Thread(aa).start();
      new Thread(aa).start();
   }
 
}
 
class TestThreadimplements Runnable {
   inttickets = 100;
 
   publicvoid run() {
      while (true) {
         if(tickets > 0){
            try {
                Thread.sleep(10);
            } catch (InterruptedExceptione) {
                //TODO Auto-generated catch block
                e.printStackTrace();
            }
         System.out.println("run():" + Thread.currentThread().getName()
                + "is saling ticket" + tickets--);
         }
      }
   }
}

通过睡眠10毛秒就会发生线程的同步问题,这样就会出现卖通一张票的问题;同步问题就是解决代码的原子性问题

10.同步问题的解决:通过同步语句块实现(synchronized

public class ThreadDemo1 {
   public static void main(String[] args) {
      // new TestThread().start();
      TestThread aa = new TestThread();
      // aa.setDaemon(true);
      new Thread(aa).start();
      new Thread(aa).start();
      new Thread(aa).start();
      new Thread(aa).start();
   }
 
}
 
class TestThreadimplements Runnable {
   inttickets = 100;
   String str = new String("");
   publicvoid run() {
      while (true) {
         synchronized (str) {
            if(tickets > 0){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                //TODO Auto-generated catch block
                e.printStackTrace();
            }
         System.out.println("run():" + Thread.currentThread().getName()
                + "is saling ticket" + tickets--);
         }
        }
        
      }
   }
}

通过对象的标志位进行标识,使当前的同步代码块在同一时刻只能被一个线程调用;注意同步代码块的实现是使用监视器对象实现的,所以监视器对象的创建不能在run方法中,否则不同的线程就会拥有自己的监视器对象无法达到同步的目的;

11.通过同步方法实现:将可能发生同步问题的代码抽取到同步方法中实现

public class ThreadDemo1 {
   public static void main(String[] args) {
      // new TestThread().start();
      TestThread aa = new TestThread();
      // aa.setDaemon(true);
      new Thread(aa).start();
      new Thread(aa).start();
      new Thread(aa).start();
      new Thread(aa).start();
   }
 
}
 
class TestThreadimplements Runnable {
   inttickets = 100;
 
   publicvoid run() {
      while (true) {
            sale();
 
      }
   }
 
   privatesynchronizedvoid sale() {
      if (tickets > 0) {
         try {
            Thread.sleep(10);
         } catch (InterruptedException e) {
            //TODO Auto-generated catch block
            e.printStackTrace();
         }
         System.out.println("run():" + Thread.currentThread().getName()
                + "is saling ticket" + tickets--);
      }
   }
}

12.同步代码块影响程序的执行效率

13.线程start之后只是说明当前的线程处于启动状态,不一定立即执行;代码的顺序不一定是线程启动的顺序;

14.验证同步方法所使用的监视器对象是this,实现代码块和方法的同步;

public class ThreadDemo1 {
   public static void main(String[] args) {
      // new TestThread().start();
      TestThread aa = new TestThread();
      // aa.setDaemon(true);
      new Thread(aa).start();
      try {
         Thread.sleep(1);
      } catch (InterruptedException e) {
         // TODO Auto-generated catchblock
         e.printStackTrace();
      }
      aa.str = "method";
      new Thread(aa).start();
      new Thread(aa).start();
      new Thread(aa).start();
   }
 
}
 
class TestThreadimplements Runnable {
   inttickets = 100;
   String str = new String("");
 
   publicvoid run() {
 
      if (str.equals("method")) {
         while(true){
         sale();
         }
      } else {
         while (true) {
            synchronized (this) {
                if (tickets > 0) {
                   try {
                      Thread.sleep(10);
                   } catch (InterruptedException e) {
                      //TODO Auto-generated catch block
                      e.printStackTrace();
                   }
                   System.out.println("run():"
                         + Thread.currentThread().getName()
                         + "is saling ticket" + tickets--);
                }
 
            }
         }
      }
   }
 
   privatesynchronizedvoid sale() {
      if (tickets > 0) {
         try {
            Thread.sleep(10);
         } catch (InterruptedException e) {
            //TODO Auto-generated catch block
            e.printStackTrace();
         }
         System.out.print("sale ");
         System.out.println("run():" + Thread.currentThread().getName()
                + "is saling ticket" + tickets--);
      }
   }
}

15.线程的死锁问题

public class ThreadDemo1 {
   public static void main(String[] args) {
      // new TestThread().start();
      TestThread aa = new TestThread();
      // aa.setDaemon(true);
      new Thread(aa).start();
      try {
         Thread.sleep(1);
      } catch (InterruptedException e) {
         //TODO Auto-generated catch block
         e.printStackTrace();
      }
      aa.str ="method";
      new Thread(aa).start();
      new Thread(aa).start();
      new Thread(aa).start();
   }
 
}
 
class TestThreadimplements Runnable {
   inttickets = 100;
   String str = new String("");
 
   publicvoid run() {
 
      if (str.equals("method")) {
         while(true){
         sale();
         }
      } else {
         while (true) {
            synchronized (str) {
                if (tickets > 0) {
                   try {
                      Thread.sleep(10);
                   } catch (InterruptedException e) {
                      //TODO Auto-generated catch block
                      e.printStackTrace();
                   }
                   synchronized (this) {
                     
                   }
                   System.out.println("run():"
                         + Thread.currentThread().getName()
                         + "is saling ticket" + tickets--);
                }
 
            }
         }
      }
   }
 
   privatesynchronizedvoid sale() {
      if (tickets > 0) {
         try {
            Thread.sleep(10);
         } catch (InterruptedException e) {
            //TODO Auto-generated catch block
            e.printStackTrace();
         }
 
         synchronized (str) {
 
         }
         System.out.print("sale ");
         System.out.println("run():" + Thread.currentThread().getName()
                + "is saling ticket" + tickets--);
      }
   }
}

16.线程间的通信:生产者和消费者之间的关系,生产者生产一个产品消费者才能消费一个产品;

class Producer implements Runnable {
   Q q;
 
   public Producer(Q q) {
      this.q = q;
 
   }
 
   @Override
   publicvoid run() {
      int i = 0;
      while (true) {
         synchronized (q) {
            if(q.bFull){
                try {
                   q.wait();
                } catch(InterruptedException e) {
                   // TODO Auto-generatedcatch block
                   e.printStackTrace();
                }
            }
            if (i == 0) {
               q.name ="zhangsan";
                try {
                   Thread.sleep(1);
                } catch (InterruptedException e) {
                   //TODO Auto-generated catch block
                   e.printStackTrace();
                }
                q.sex ="male";
            } else {
                q.name ="lisi";
                q.sex ="female";
            }
            i = (i + 1) % 2;
            q.bFull =true;
            q.notify();
           
         }
      }
 
   }
 
}
 
class Consumerimplements Runnable {
 
   Q q;
 
   public Consumer(Q q) {
      this.q = q;
   }
 
   @Override
   publicvoid run() {
      while (true) {
         synchronized (q) {
           if(!q.bFull){
                try {
                   q.wait();
                } catch(InterruptedException e) {
                   // TODO Auto-generatedcatch block
                   e.printStackTrace();
                }
            }
            System.out.print(q.name);
            System.out.println(" : " +q.sex);
            q.bFull =false;
            q.notify();
         }
      }
 
   }
 
}
 
class Q {
   String name;
   String sex;
   Boolean bFull =false;
}
 
publicclass ThreadCommunation {
   publicstaticvoid main(String[] args) {
      Q q = new Q();
      new Thread(new Producer(q)).start();
      new Thread(new Consumer(q)).start();
 
   }
 
}

以上的代码中将q作为共同的监视器,解决了同步问题;为了解决线程多次访问同一个资源使用了线程间的通信;通过q.wait()方法将当前的线程置入等待状态,释放cpu的使用权;使用q.notify()方法通知其他线程启动;

将以上代码进行优化后的代码:

class Producer implements Runnable {
   Q q;
 
   public Producer(Q q) {
      this.q = q;
 
   }
 
   @Override
   publicvoid run() {
      int i = 0;
      while (true) {
         synchronized (q) {
            if (i == 0) {
                q.put("zhangsan","male");
            } else {
                q.put("lisi","female");
            }
            i = (i + 1) % 2;
         }
      }
 
   }
 
}
 
class Consumerimplements Runnable {
 
   Q q;
 
   public Consumer(Q q) {
      this.q = q;
   }
 
   @Override
   publicvoid run() {
      while (true) {
         synchronized (q) {
            q.get();
         }
      }
 
   }
 
}
 
class Q {
   private Stringname;
   private Stringsex;
   private BooleanbFull = false;
   public synchronized voidput(String name, String sex) {
      if (bFull) {
         try {
            wait();
         } catch (InterruptedException e){
            // TODO Auto-generated catchblock
            e.printStackTrace();
         }
      }
 
      this.name = name;
      try {
         Thread.sleep(1);
      } catch (InterruptedException e) {
         // TODO Auto-generated catchblock
         e.printStackTrace();
      }
      this.sex = sex;
      bFull = true;
      notify();
 
   }
 
   public synchronized voidget() {
      if (!bFull) {
         try {
            wait();
         } catch (InterruptedException e){
            // TODO Auto-generated catchblock
            e.printStackTrace();
         }
      }
      System.out.print(name);
      System.out.println(" : "+ sex);
      bFull = false;
      notify();
   }
 
}
 
publicclass ThreadCommunation {
   publicstaticvoid main(String[] args) {
      Q q = new Q();
      new Thread(new Producer(q)).start();
      new Thread(new Consumer(q)).start();
 
   }
 
}

上面的代码是将对Q类的处理都抽象为自己的方法,同时这些方法都是线程安全的,更加符合面向对象的思想;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值