了解进程和线程: 在多任务的操作系统中,每个独立执行的程序称为进程,也是正在进行的程序。我们现在使用的操作系统一般都是多任务的,能同事执行多个任务。在实际中,操作系统负责CUP等设备的资源分配。 一个进程可以包括多个或一个线程,一个线程就是一个程序内部的一条执行线索。如果一个程序中实现了多段代码交替执行,就需要产生多个线程,并制定每个线程上要运行的代码段,这就是多线程。 简单举例: package com.thread; public class ThreadOneText { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub boolean flag = true; while (flag) { System.out.println("main()" + Thread.currentThread().getName()); } new Text().start(); } } class Text extends Thread{ public void run() { while (true) { System.out.println("sub()" + Thread.currentThread().getName()); } } } l 使用Thread类创建线程,要将一段代码放在一个新的线程上运行,就必须把代码放在一个线程的run()方法中,却run()函数所在的类必须是Thread的子类。到过来看,我们要实现多线程,必须写一个类继承Thread类,子类要覆盖run函数,在子类的run函数调用新线程上的代码。 l 启用一个新线程,我们不是直接调用一个thread子类的run函数,而是调用thread子类的 start函数。Thread类的start函数产生一个新的thread对象,并在该对象上运行run函数,根据面向对象时的多态性,在该线程上实际运行Thread子类的对象的run方法。 l 当run函数执行完毕,线程就执行完毕了。 后台线程与联合线程: 如果我们在启用一个线程对象之前就调用了setDaemon (true)这个线程就变成了后台线程。 对于java程序来说,只要有一个前台线程在运行,这个进程就不会结束。如果一个进程中只有一个后台线程在运行,这个进程就会结束, Thread t = new Text(); t.setDaemon(true);//这里变成了后台线程,程序会自动结束。 t.start(); //new Text().start();//这里是前台线程,程序是不会结束的。 Join()方法,是合并线程,也可以带参数,带上参数表示该线程终止的时间。也就是该线程执行多长时间。简单举例:package com.thread; public class ThreadThree { /** * @param args */ public static void main(String[] args) throws Exception{ // TODO Auto-generated method stub Thread t = new Thread(new Thread3()); t.start(); int index = 0; while(true){ if(index++ ==100) t.join(10000); System.out.println(Thread.currentThread().getName()); } } } class Thread3 implements Runnable{ @Override public void run() { // TODO Auto-generated method stub while(true){ System.out.println(Thread.currentThread().getName()); } } } 注意:一个Thread对象代表一个线程,无论你start()方法调用几次都只代表一个线程。 使用Runnable接口创建多线程: 适合于相同的程序代码的线程去处理同一资源的情况,把虚拟的CUP同程序的代码,数据有效分离,体现了面向对象的设计思想。也可以避免Java虚拟机的单继承性带来的局限。举例:火车票一百张,四个窗口去买。 要用继承Thread类去处理,非常的麻烦,我们可以实现Runnable接口,就很简单,就验证了相同的程序代码的线程去处理同一资源的情况。 package com.thread; public class ThreadThree { /** * @param args */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub // Thread t = new Thread(new Thread3()); // t.start(); // int index = 0; // while(true){ // if(index++ ==100) t.join(10000); // System.out.println(Thread.currentThread().getName()); // } Thread3 t = new Thread3(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); } } class Thread3 implements Runnable { int ticket = 100; @Override public void run() { // TODO Auto-generated method stub while (true) { if (ticket > 0) System.out.println(Thread.currentThread().getName() + "is selling" + ticket--); } } } 在线程的安全中,也就是同步问题,可以加一个synchronized(){}括号中必须是一个对象,可以是任意对象。while (true) { synchronized (str) {//代码块 if (ticket > 0) { try { Thread.sleep(10); } catch (Exception e) { } System.out.println(Thread.currentThread().getName() + "is selling" + ticket--); } } synchronized(标志位){}注意这里的标志位,默认开始是1,当一个线程进入时,就把标志位设置为0.其他的线程就不允许进入。Synchronized这个代码块之间要保持原子性。标志位也叫监视器。上面的代码使用代码块实现了同步,也可以使用函数的方法实现同步。 public synchronized void sale() {}这样的同步方法,表示为使用的关键字是this。将上面的代码块的标志位该为this时,也可以实现同步。 死锁现象: package com.thread; public class ThreadThree { /** * @param args */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub // Thread t = new Thread(new Thread3()); // t.start(); // int index = 0; // while(true){ // if(index++ ==100) t.join(10000); // System.out.println(Thread.currentThread().getName()); // } Thread3 t = new Thread3(); new Thread(t).start(); try { Thread.sleep(10); }catch(Exception e){ } t.str = new String("method"); new Thread(t).start(); // new Thread(t).start(); // new Thread(t).start(); } } class Thread3 implements Runnable { int ticket = 100; String str = new String(""); @Override public void run() { if (str.equals("method")) { sale(); } else { while (true) { synchronized (str) { if (ticket > 0) synchronized(this){} try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "is selling" + ticket--); } } } } public synchronized void sale() { while (true) { synchronized(str){} if (ticket > 0) { try { Thread.sleep(100); } catch (Exception e) { } System.out.println(Thread.currentThread().getName() + "is selling" + ticket--); } } } } 线程见的通信: 生产者和消费者: package com.thread; public class ConsumerandProduct { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Q q = new Q(); new Thread(new Product(q)).start(); new Thread(new Consumer(q)).start(); } } class Product implements Runnable { Q q; public Product(Q q) { this.q = q; } @Override public void run() { // TODO Auto-generated method stub int i = 0; while (true) { synchronized (q) { if(q.b){ try { q.wait(); } catch (Exception e) { } } if (i == 1) { q.name = "zhangsan"; q.sex = "male"; } else { q.name = "lisi"; q.sex = "female"; } q.b = true; q.notify(); } i = (i + 1) % 2; } } } class Consumer implements Runnable { Q q; public Consumer(Q q) { this.q = q; } @Override public void run() { // TODO Auto-generated method stub while (true) { synchronized (q) { if(!q.b){ try { q.wait(); } catch (Exception e) { } } System.out.print(q.name + " "); System.out.print(q.sex); System.out.println("/n"); q.b = false; q.notify(); } } } } class Q { String name = "unknow"; String sex = "unknow"; boolean b = false; } 线程并发库: 了解常用的类:在java.util.concurrent.atomic包中: AtomicInteger AtomicIntegerArray 这些都是建立在同步的基础之上。在一个方法中(数组),如果有多个线程去操作,很可能是不安全的。 Java5的线程并发库,参照java.util.concurrent包及子包。了解线程池的概念:只需要记住Executeous类即可. package com.thread; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class AtomicText { /** * @param args */ public static void main(String[] args) { ExecutorService servers = Executors.newFixedThreadPool(3);// 创建一个线程池 for (int i = 0; i < 10; i++) { final int squence = i; servers.submit(new Runnable() { @Override public void run() { // TODO Auto-generated method stub for (int j = 0; j < 5; j++) { System.out.println(Thread.currentThread().getName() + " " + "is serving" + squence + "task" + "loop up" + j); } } }); } } } 了解 newCachedThreadPool () 是创建根据需要的任务创建多个线程池。 newFixedThreadPool(int nThreads) 创建固定的线程池。 newSingleThreadExecutor() 创建单个线程池。 下面讲解创建定时器: newScheduledThreadPool(int corePoolSize) 举例: ScheduledExecutorService scheduleserver = Executors .newScheduledThreadPool(5); scheduleserver.scheduleAtFixedRate(new Runnable() { @Override public void run() { // TODO Auto-generated method stub System.out.println("go!!!"); } }, 1,2, TimeUnit.SECONDS); }
多线程
最新推荐文章于 2024-01-17 16:35:13 发布