进程:正在执行的一段程序,操作系统分配资源的单元。
进程拿到的是一段连续的地址(操作系统分配的,通过页中断,实际物理上并不连续)。
线程(栈,程序计数器,线程状态):(在进程里)是进程的具体执行单元,即一个进程最少有一个线程。
进程和线程都是由操作系统调度的。线程不能决定什么时候执行,只能由操作系统控制。
线程不安全:有共享区域、多线程对其进行写入。
线程安全:有共享区域,只读取,或者一个线程写,其他线程读取。
加锁:只要锁的是同一个对象,都必须等一个线程走完,再下一个线程,注:主线程和其他线程没有什么区别,都看成线程。
@override,重写继承的方法
wait()进程等待并且释放锁,notify()通知其他线程可以走,notifyAll()通知所有线程可以往wait下走(所有进程进行竞争),先通知,再wait(因为会释放锁)。
同步:发完消息收到返回的消息再往下走。
异步:发消息的同时往下走,消息回来,再对回来的消息进行处理。
多线程:IO密集型(硬盘/内存,读/写密集):可以理解为简单的业务逻辑处理,比如计算1+1=2,但是要处理的数据很多,每一条都要去插入数据库,对数据库频繁操作。
计算密集型(cpu密集):可以理解为 就是处理繁杂算法的操作,对硬盘等操作不是很频繁,比如一个算法非常之复杂,可能要处理半天,而最终插入到数据库的时间很快。线程数量不建议超过cpu数量,因为切换进程会损耗效率.
一个线程并不会截获另一个线程的异常。
创建线程的方法:
(1)Thread t1 = new Thread(new a());
(2)Thread t2 = new Thread(new Runnable()); //匿名类
@override //重写继承的匿名类的方法
public void run() {
}
(3)Thread t3 = new Thread() -> { //以下东西在run方法里,同上
synchronized(Deal.a){
/
}
}
14.锁
Lock l = new ReentrantLock();
ReadWriteLock l2 = new ReentrantReadWriteLock();
Thread t1 = new Thread() -> {
l.lock(); //锁
l2.readLock().lock(); //读锁
l2.writeLock().lock(); //写锁
try{
}finally{
l2.writeLock().unlock();
l2.readLock().unlock(); //后锁的先解
l.unlock(); //解锁
}
15.线程池(Thread Pool):把一个或多个线程通过统一的方式进行调度和重复使用的技术,避免了因为线程过多而带来使用上的开销。
//进程池的使用:
ThreadPoolExecutor e = new ThreadPoolExecutor(2, 2, 1000,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10),Executors.defaultThreadFactory()
,new ThreadPoolExecutor.CallerRunsPolicy());
//参数:核心线程数,最大线程数(包括核心线程数),闲置超时时间,时间单位,任务队列(使用 execute() 或 submit() 方法提交的任务都会存储在此队列中。),
//工厂(为线程池提供创建新线程的线程工厂)
//拒绝策略:
// DiscardPolicy():丢弃掉该任务但是不抛出异常,不推荐这种(导致使用者没觉察情况发生)
// DiscardOldestPolicy():丢弃队列中等待最久的任务,然后把当前任务加入队列中。
// AbortPolicy():丢弃任务并抛出 RejectedExecutionException 异常(默认)。
// CallerRunsPolicy():由主线程负责调用任务的run()方法从而绕过线程池直接执行
// ,既不抛弃任务也不抛出异常(当最大线程数满了,任务队列中也满了,再来一个任务,由主线程执行)
//以上new ThreadPoolExecutor.CallerRunsPolicy()拒绝策略:由主线程负责调用任务的run()方法从而绕过线程池直接执行,
// 既不抛弃任务也不抛出异常(当最大线程数满了,任务队列中也满了,再来一个任务,由主线程执行)
Wapper wapper = new Wapper();
AddWater addWater = new AddWater(wapper);
DecWater decWater = new DecWater(wapper);
e.execute(addWater); //执行线程
e.execute(decWater);
e.shutdown(); //当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,
// 否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。
16.流:操作之后即被回收
public static void main(String[] args) {
//流 Stream
Stream<Integer> s = Stream.of(1,3,4,32,60,70,80,90,120,130);
// List<Integer> list = null;
// list.stream();
//数组中的一个元素走完并输出,再走下一个!!!
int re = s
.filter(e -> {return e >= 50 && e <= 100;}) //过滤
//
// .map(i -> i*2)
.peek(System.out::println) //中间过程,返回流
// .limit(4) //限制3个输出
// .skip(1) //跳过一个
// .distinct() //去重
// .peek(System.out::println)
// .sorted() //排序
// .peek(System.out::println) //
// .flatMap(e -> {
// Integer[] ss = new Integer[e.length()];
//
// for(int i=0;i<ss.length;i++){
// ss[i] = (int)e.charAt(i);
//
// }
// return Stream.of(ss);
// })
.reduce(0,Integer::sum); //输出操作后数组的和,结束过程:到达结束过程才开始执行流
// 或者 .reduce(Integer::sum).get();
// System.out.println(re);
// .collect(Collectors.toList()) //到这里才开始从头执行!!执行以上的操作,惰性,结束过程
// .forEach(System.out::println); //结束过程
// System.out.println(
// s.skip(3).map(i -> i+1).filter(i -> i >= 5).collect(Collectors.toList())
// );
//skip跳过前三个数,map:对第四个数开始每个数数加一并返回(即把一个数换成另外一个),filter:过滤掉i < 5的数
//操作完,s就被回收
//注意:流操作完返回的东西拿对应的参数接!!!
动态规划:01背包
动态规划目的:记录每一步的状态或者是每一步需要的值,方便之后的操作:可以直接使用之前记录的状态,避免了重复计算,增加了代码的效率。
/**
* 动态规划:01背包
* @param w 物品重量数组
* @param y 物品价值数组
* @param bagW 背包容量
* @return 背包能放物品的最大价值
* 计算每一个背包容量,放入每一个物品时的最大价值
*/
private static int cal(int[] w, int[] y, int bagW) {
int dp[][] = new int[w.length][++bagW];
for(int i = 0;i < w.length;i++){
if(i == 0){ //初始化第一行,即只有第一个物品时,每个背包容量(0-bagW)的最大价值
for(int k = w[0];k < bagW;k++){ //能放下第一个物品时,背包才有价值
dp[i][k] = y[0];
}
}else {
for (int j = 0; j < bagW; j++) { //第二行:即为放入第二个物品开始
if(j < w[i]){ //如果背包容量 < 要放入物品的容量,则直接复制上一行
dp[i][j] = dp[i -1][j];
}else if (dp[i -1][j - w[i]] + y[i] > dp[i - 1][j]) {
//如果当前背包容量减去当前放入物品的体积再放入当前物品之后的价值,大于上一行(即不放入当前物品背包的最大价值),则更新为放入当前物品的背包价值
dp[i][j] = dp[i -1][j - w[i]] + y[i];
}else { //小于的话,则复制上一行
dp[i][j] = dp[i-1][j];
}
}
}
}
for (int[] ints : dp) { //遍历输出每一行的数
for (int anInt : ints) {
System.out.print(anInt+" ");
}
System.out.println();
}
return dp[w.length-1][bagW-1]; //最后一行最右边的数即为背包最大价值
// 因为背包的容量为(0-bagW),所以之前++bagW
}
public static void main(String[] args) {
int[] w = new int[]{3,2,1,4,7};
int[] y = new int[]{10,3,4,2,5};
System.out.println(cal(w,y,10));
}