1.throws和throw的区别
throws使用在函数外,是编译时的异常,throw使用在函数内,是运行时的异常
使用方法
public int method(int[] arr) throws NullPointerException{}
public int method(int[] arr){
if(arr==null){
throw new NullPointerException (“数组的引用不能为空”);
}
}
throws 抛出的是异常类,可以抛出多个,用逗号隔开,throw抛出的是异常对象
2.Java中的四种权限
public protected default private,其中如果什么都没有写,就是default
3.多线程
多线程的好处:解决了多个程序同时运行的问题。
多线程的弊端:线程太多会导致效率降低
其实应用程序的执行都是CPU在做着快速的切换完成的。这个切换是随机的
java中运行垃圾回收是:System.gc();
创建线程方式一并使用
代码如下:
package com.itcast.test; /** * 创建线程方式 * 1.子类继承Thread类,子类覆盖父类中的run方法,将线程要执行的代码写在run方法中 * 2.建立子类对象的同时线程也被创建 * 3.通过调用start方法开启线程 * @author yxl * */ public class ThreadSub extends Thread { @Override public void run() { // 这里面是线程要执行的代码 for (int i = 0; i < 10; i++) { System.out.println(i+"---"+Thread.currentThread().getName()); } } public ThreadSub(String threadName){ } }
package com.itcast.test; public class Demo { public static void main(String[] args) { //创建线程并调用第一种方式 ThreadSub threadSub = new ThreadSub("线程1"); ThreadSub threadSub2 = new ThreadSub("线程2"); threadSub.start();// 开启线程,调用run方法 // threadSub.run();如果直接调用run()方法就是只调用主线程执行 threadSub2.start(); } }
创建线程方式二推荐使用这种方式
代码如下:
package com.itcast.test; /** * 创建线程的第二种方式,实现Runnable接口。推荐使用这种方式 * 1.定义类实现Runnable接口 * 2.覆盖接口中的run方法,并将线程的任务代码封装到run方法中 * 3.通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数 * 的参数进行传递,通过对象调用run方法 * 4.调用线程对象的start()开启线程 * @author yxl * */ public class ImplementThread implements Runnable { @Override public void run() { // 这里面是线程要执行的代码 for (int i = 0; i < 10; i++) { System.out.println(i+"---"+Thread.currentThread().getName()); } } }
package com.itcast.test; public class Demo { public static void main(String[] args) { //创建线程并调用第二种方式,推荐使用第二种方式 ImplementThread thread = new ImplementThread(); Thread t =new Thread(thread); t.start(); Thread t2 =new Thread(thread); t2.start(); } }
同步解决线程安全问题(JDK1.5之前版本使用的方式)
Object object = new Object();
synchronized (object) {
}
相当于lock锁
/**
* 同步函数
* 同步函数使用的锁是this,建议使用同步代码块锁
*/
public synchronized void Show() {
}
线程间通讯:
多个线程在处理同一资源,但是任务却不同。
生产者消费者模式:
代码如下:
package com.itcast.test1; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /* * 等待唤醒机制 * 1.wait():让线程处于冻结状态,被wait的线程会被存储到线程池中 * 2.notify():唤醒线程池中一个线程(任意) * 3.notifyAll():唤醒线程池中的所有线程。 * 这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法,必须要明确到底操作的是哪个锁上的线程。 * 以上方法都是定义在Object类中,因为这些方法是监视器的方法,监视器其实就是锁 * jdk1.5以后将同步和锁封装成了对象,并将操作锁的隐士动作变成了显示动作 。 * Lock接口:出现替代了同步代码块或者同步函数。将同步的隐士锁操作变成现实锁操作,同时更为灵活,可以一个锁上加上多组监视器 * lock():获取锁,unlock():释放锁,通常需要定义在finally代码块中。 * Condition接口:出现替代了Object中的wait notify notifyAll方法,将这些监视器方法单独进行了封装, * 变成Condition监视器对象。可以任意锁进行组合。 * await() * signal() * signalAll() */ /** * 生产资源类 * @author yxl * */ public class Resourse { private String name; public boolean flag = false;// 用来标识用的,为了实现生产一个,消费一个,为true,表示生产者有数据 Lock lock = new ReentrantLock(); Condition conditionProductor = lock.newCondition(); Condition conditionCustomer = lock.newCondition(); int count = 0; public String getName() { return name; } public void setName(String name) { this.name = name; } public void set(String name) { lock.lock(); try { while (flag) { conditionProductor.await(); } setName(name+count); count++; System.out.println(Thread.currentThread().getName()+"-----"+getName()); flag = true; conditionCustomer.signal(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { lock.unlock(); } } public void out(){ lock.lock(); try { while (!flag) { conditionCustomer.await(); } System.out.println(Thread.currentThread().getName()+"-----"+name); flag = false; conditionProductor.signal(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { lock.unlock(); } } }
package com.itcast.test1; /** * 生产者类 * @author yxl * */ public class Productor implements Runnable { Resourse resourse ; public Productor(Resourse resourse){ this.resourse = resourse; } @Override public void run() { while(true){ resourse.set("生产者名称"); } } }
package com.itcast.test1; /** * 消费者类 * @author yxl * */ public class Customer implements Runnable { Resourse resourse ; public Customer(Resourse resourse){ this.resourse = resourse; } @Override public void run() { while(true){ resourse.out(); } } }
package com.itcast.test1; public class MainDemo { public static void main(String[] args) { Resourse resourse = new Resourse(); Productor productor = new Productor(resourse); Customer customer = new Customer(resourse); Thread thread1 = new Thread(productor); thread1.start(); Thread thread2 = new Thread(customer); thread2.start(); Thread thread3 = new Thread(productor); thread3.start(); Thread thread4 = new Thread(customer); thread4.start(); } }
wait和sleep的区别:
1.wait可以指定时间也可以不指定,sleep必须指定时间
2.在同步中,对CPU的执行权和锁的处理方式不同
wait释放执行权,释放锁,sleep释放执行权,不释放锁,因为它一定有时间的限制,不需要释放锁。
终止线程的方法:
1.可以使用interrupt()方法将线程从冻结状态强制恢复到运行状态中来,让线程具备CUP的执行资格。当然强制动作会发生InterruptedException,记得要处理,在异常处理中使用标记来终止线程
2.也可以使用thread2.setDaemon(true);将线程设置为守护线程,也就是后台线程,所有前台线程都结束,后台线程自动结束
代码如下:
package com.itcast.test2; public class StopThread implements Runnable { private boolean flag = true; @Override public synchronized void run() { while(flag){ try { wait(); } catch (InterruptedException e) { System.out.println(Thread.currentThread().getName()); //出错的时候,可以设置标记 flag = false; } System.out.println(Thread.currentThread().getName()); } } }
package com.itcast.test2; public class MainDemo { public static void main(String[] args) { StopThread stopThread = new StopThread(); Thread thread = new Thread(stopThread); thread.start(); thread.setPriority(Thread.MAX_PRIORITY);//设置线程的优先级,值为1-10 Thread thread1 = new Thread(stopThread); thread1.start(); Thread thread2 = new Thread(stopThread); thread2.setDaemon(true);//第二种终止线程的方法,将线程设置为守护线程,也就是后台线程 //所有前台线程都结束,后台线程自动结束 thread2.start(); for (int i = 0; i < 100; i++) { if (i==58) { thread.interrupt();//调用interrupt()方法终止线程 thread1.interrupt(); } System.out.println(i); } } }