欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Java基础笔记

时间:2023-06-11
一、 java基础 1、java多线程基础 1) 多线程的创建方式 1.多线程创建方式1

package com.qyl.springboot.controller;// 1.创建一个子类类继承Threadclass MyThread extends Thread{ //2.在子类中重写Thread的run()方法 线程要做的事写到run()方法中 @Override public void run() { for (int i = 0; i < 100; i++) { if (i % 2 == 0){ System.out.println(i+"---"+Thread.currentThread().getName()); } } }};public class ThreadTest { public static void main(String[] args) { // 3.创建该子类的对象 //主线程执行 MyThread myThread = new MyThread(); MyThread myThread1 = new MyThread(); //4.通过此对象调用start方法 //创建出来的线程执行 myThread.start(); myThread1.start();//乡启动多个就多创建对象即可 for (int i = 0; i < 100; i++) { if (i % 2 == 0){ System.out.println(i+ " ++++++++++++++-"+Thread.currentThread().getName()); } }//这种方法也可以 匿名子类 System.out.println("/"); new Thread(){ @Override public void run() { for (int i = 0; i < 100; i++) { if (i % 2 != 0){ System.out.println(Thread.currentThread().getName()+""+ i ); } } } }.start(); }}

输出结果:

48---Thread-078---Thread-150---Thread-018 ++++++++++++++-main52---Thread-080---Thread-182---Thread-184---Thread-1

2、多线程创建方式2

实现Runnable接口

1.创建一个实现了Run那边了接口的类

2.实现类去实现Runable中的抽象方法

3.创建实现类的对象

4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象

5.通过Thread类的对象调用start()方法

package com.qyl.springboot.controller;//1.创建一个实现了Run那边了接口的类class MyRunnable implements Runnable{ //2.实现类去实现Runable中的抽象方法 @Override public void run() { for (int i = 0; i < 100; i++) { if (i % 2 == 0){ System.out.println(""+i+ " ++++++++++++++-"+Thread.currentThread().getName()); } } }}public class RunableTest { public static void main(String[] args) { //3.创建实现类的对象 MyRunnable m1 = new MyRunnable(); //4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象 Thread thread = new Thread(m1); thread.setName("liudeh"); thread.start(); Thread t2 = new Thread(m1); t2.setName("liudsssssssssseh"); t2.start(); }}

2.线程生命周期 创建 调用start()就绪 sleep()时间到,join()结束,获取同步锁,notify()/notifyALL(),resume()阻塞 失去cpu执行权,或者yield()运行 sleep(),join(),等待同步锁,wait(),suspend()死亡 执行完run(),调用stop(),出现Error/Exception且没处理 3.线程同步 1.同步代码块

/** * 线程同步与安全 * 处理共享数据的时候会出现线程安全问题 * 加锁解决 * 4.在java中,通过同步机制来解决线程安全问题 * 方式一 : 同步代码块 * synchronized (同步监视器) { * //需要被同步的代码 (吃操作共享数据的代码就是需要被同步的代码) * } * 说明: 1.(吃操作共享数据的代码就是需要被同步的代码) * 2.同步监视器就是 锁 任何类的对象都能充当锁 * 锁的要求 : 多个线程供用同一把锁 * 哪怕你用一个狗 dag对象都可以 * 方式二 : 同步方法 * * * 5.同步的方式虽然解决了线程安全 * 缺点是同步代码块里面是单线程 */

package com.qyl.java;class Window implements Runnable{ private int titck = 100; Object object = new Object(); @Override public void run() { while (true){ //同步代码块 synchronized(object){ if (titck>0){ System.out.println(Thread.currentThread().getName()+" 卖票-----票号码为: " + titck ); titck--; }else { break; } } } }}public class SyncThread { public static void main(String[] args) { Window m1 = new Window(); Thread t1 = new Thread(m1); Thread t2 = new Thread(m1); Thread t3 = new Thread(m1); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t1.start(); t2.start(); t3.start(); }}

注意:implement Runnable 的时候 this(当前对象 ) 就可以当做锁 extends Threads的时候 不行

2.同步方法

// 1.一种情况可以直接把run改为同步的,但是要注意场景class Window implements Runnable{ private int titck = 100; Object object = new Object(); @Override public synchronized void run() { while (true){ //同步代码块 synchronized(this){ if (titck>0){ System.out.println(Thread.currentThread().getName()+" 卖票-----票号码为: " + titck ); titck--; }else { break; } } } }}

1.同步方法解决Runnable

package com.qyl.java;class Window implements Runnable{ private int titck = 100; Object object = new Object(); @Override public void run() { while (true){ sync(); } } private synchronized void sync (){ //同步监视器就是this //同步代码块 if (titck>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 卖票-----票号码为: " + titck ); titck--; } }}public class SyncThread { public static void main(String[] args) { Window m1 = new Window(); Thread t1 = new Thread(m1); Thread t2 = new Thread(m1); Thread t3 = new Thread(m1); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t1.start(); t2.start(); t3.start(); }}

2.同步方法解决thread

package com.qyl.java;class Windows extends Thread { private static int tickets = 100; private static Object object = new Object(); @Override public void run() { while (true) { //同步代码块 show(); } }private static synchronized void show(){ //加个static 就可以了 if (tickets > 0) { try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 卖票-----票号码为: " + tickets); tickets--; }}}public class extendsThread { public static void main(String[] args) { Windows w1 = new Windows(); Windows w2 = new Windows(); Windows w3 = new Windows(); w1.setName("窗口1"); w2.setName("窗口2"); w3.setName("窗口3"); w1.start(); w2.start(); w3.start(); }}

4.Thread 的常用方法介绍: 1) start():

启动当前线程,调用当前线程的run()方法 。

2) run():

通常是重写Thread 的run()方法 将线程要做的事情声明在该方法中

3) currentThread() :

Thread 的静态方法 获取到当前线程

4)getName() setName():

给线程名字的方法

package com.qyl.springboot.controller;class MyThread1 extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { if(i % 2 == 0 ){ try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Thread.currentThread().setName("lalala"); 线程命名 方式1 System.out.println(Thread.currentThread().getName()+"*******"+i); } } }}public class ThreadTest1 { public static void main(String[] args) { MyThread1 myThread1 = new MyThread1(); //线程命名 方式2 myThread1.setName("huren"); myThread1.start(); //给主线程命名 Thread.currentThread().setName("zongguanjun"); for (int i = 0; i < 100; i++) { if(i % 2 == 0 ){ //Thread.currentThread().setName("lalala"); 线程命名 System.out.println(Thread.currentThread().getName()+"*******///"+i); } } }}------------------------通过构造器命名线程package com.qyl.springboot.controller;class MyThread1 extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { if(i % 2 == 0 ){ //Thread.currentThread().setName("lalala"); 线程命名 方式1 System.out.println(Thread.currentThread().getName()+"*******"+i); } if(i % 20 == 0){ yield(); } } } //线程命名方式3 通过构造器命名 public MyThread1(String name){ super(name); }}public class ThreadTest1 { public static void main(String[] args) { MyThread1 myThread1 = new MyThread1("sssssss"); //线程命名 方式2 myThread1.setName("huren"); myThread1.start(); //给主线程命名 Thread.currentThread().setName("zongguanjun"); for (int i = 0; i < 100; i++) { if(i % 2 == 0 ){ //Thread.currentThread().setName("lalala"); 线程命名 System.out.println(Thread.currentThread().getName()+"*******///"+i); } } }}

5)yiel ():

释放当前cpu的执行权

6)join ():

在线程a中调用线程b的join()方法,此时线程a进入阻塞状态,等b执行完之后,a结束阻塞继续执行

7) stop():

强制结束该线程,不推荐使用

8) sleep(lang millitime):

当前线程睡眠指定的一段时间

9) isAlive()

判断当前线程是否存活

10)property()get,set

线程的优先级 1-10 默认5

public void newRunnableMethod () { new Thread(new Runnable() { @Override public void run() { // 存放所有openid List openids = new ArrayList<>(); List usersGuid = new ArrayList<>(); SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false); Task_Info_News_ReadMapper mapper = sqlSession.getMapper(Task_Info_News_ReadMapper.class); try{ // 组装info_news_read 表所需要的数据,并存入数据库中 for(int i = 0; i< list.size();i++){ String strUserGuid = (String)list.get(i).get("strUserGuid"); // 通过临时存放usersGuid,去重(对根据范围查出数据进行去重) if(!usersGuid.contains(strUserGuid)){ usersGuid.add(strUserGuid); // 获取openid Object strOpenid = list.get(i).get("strOpenid"); // 如果openid不为空,则放入openids集合中(用来推送模板消息) if(strOpenid != null){ openids.add(strOpenid.toString()); } list.get(i).put("strGuid", UUID.randomUUID().toString()); list.get(i).put("strNewsGuid",info_News.getStrGuid()); list.get(i).put("strCreator",info_News.getStrCreator()); list.get(i).put("dtCreateTime", info_News.getDtCreateTime()); mapper.insertMap(list.get(i)); } if(i % 1000 == 0 || i == list.size() - 1){ sqlSession.commit(); sqlSession.clearCache(); } } }catch (Exception e) { logger.info("事物已回滚"); loggerErr.info("发布任务失败 ==>" + e.getMessage()); sqlSession.rollback(); e.printStackTrace(); }finally { sqlSession.close(); } PropertiesUtils utils = null; try { utils = new PropertiesUtils("global/param_hexi.properties"); } catch (Exception e) { logger.info("global/param_hexi.properties 文件找不到"); e.printStackTrace(); return; } // 微信模板消息,任务的模板id if(openids.size() > 0){ String template_id = utils.getProperty("template_id"); sendNewsToWebchatUser(template_id, openids, info_News); } } }).start();}

//不同的写法

package com.qyl.java;class MyThreadRunnable implements Runnable{ @Override public void run() { for (int i = 0; i < 100; i++) { if (i % 2 == 0){ System.out.println(Thread.currentThread().getName() + "=================" +i); } } }}public class SyncThreadTest { public static void main(String[] args) { MyThreadRunnable m1 = new MyThreadRunnable(); Thread t1 = new Thread(m1); t1.setName("子线程1"); t1.start(); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { if (i % 2 != 0){ Thread.currentThread().setName("主线程"); System.out.println(Thread.currentThread().getName() + "=================" +i); } } } }).start(); }}

5.使用同步机制将单例模式中的懒汉式改写为线程安全的 1.效率较低的方式

package com.qyl.java;public class BankTest {}class Bank{ private Bank(){} private static Bank instance = null; public static Bank getInstance(){ //加上synchronized就变成线程安全的了 synchronized () { if (instance == null){ instance = new Bank(); } return instance; } }}

2.效率高点

package com.qyl.java;public class BankTest {}class Bank{ private Bank(){ } private static Bank instance = null; public static Bank getInstance(){ //加上synchronized就变成线程安全的了 if (instance == null) { synchronized (Bank.class) { if (instance == null) { instance = new Bank(); } } } return instance; }}

6.线程死锁问题 1.死锁案例

package com.qyl.java;public class SiSuo { public static void main(String[] args) { StringBuffer s1 = new StringBuffer(); StringBuffer s2 = new StringBuffer(); new Thread(){ @Override public void run() { synchronized (s1){ s1.append("a"); s2.append("1"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s2){ s1.append("b"); s2.append("2"); System.out.println(s1); System.out.println(s2); } } } }.start(); new Thread(new Runnable() { @Override public void run() { synchronized (s2){ s1.append("c"); s2.append("3"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s1){ s1.append("d"); s2.append("4"); System.out.println(s1); System.out.println(s2); } } } }).start(); }}

2.解决线程安全问题三 Lock锁

Inspection ‘在使用阻塞等待获取锁的方式中,必须在try代码块之外,并且在加锁方法与try代码块之间没有任何可能抛出异常的方法调用,避免加锁成功后,在finally中无法解锁。
说明一:如果在lock方法与try代码块之间的方法调用抛出异常,那么无法解锁,造成其它线程无法成功获取锁。
说明二:如果lock方法在try代码块之内,可能由于其它方法抛出异常,导致在finally代码块中,unlock对未加锁的对象解锁,它会调用AQS的tryRelease方法(取决于具体实现类),抛出IllegalMonitorStateException异常。
说明三:在Lock对象的lock方法实现中可能抛出unchecked异常,产生的后果与说明二相同。’ options

package com.qyl.java;import java.util.concurrent.locks.ReentrantLock;class WindowLock implements Runnable{ private int titck = 100; //1.实例化一个lock private ReentrantLock lock = new ReentrantLock(); @Override public void run() { while (true){ try { lock.lock(); //2.调用lock() if (titck> 0){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 卖票-----票号码为: " + titck ); titck--; } else { break; } } finally { //调用解锁方法 lock.unlock(); } } }}public class LockTest { public static void main(String[] args) { WindowLock m1 = new WindowLock(); Thread t1 = new Thread(m1); Thread t2 = new Thread(m1); Thread t3 = new Thread(m1); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t1.start(); t2.start(); t3.start(); }}

7.wait() notify() 1.两个线程交叉打印100以内的数

package com.qyl.springboot.controller;// 2个线程交叉打印100以内的数字class WaitNotify implements Runnable{ private int number = 1; @Override public void run() { while (true){ synchronized (this) { //唤醒全部线程 //notifyAll(); //唤醒线程 notify(); if (number<=100){ //睡眠 不释放线程 不释放锁 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" ---打印了 : "+number); number++; //等待 但是释放线程 释放锁 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } }else { break; } } } }}public class WaitNotifyTest { public static void main(String[] args) { WaitNotify w1 = new WaitNotify(); Thread t1 = new Thread(w1); Thread t2 = new Thread(w1); t1.setName("线程1 +++++: "); t2.setName("线程2 -----: "); t1.start(); t2.start(); }}

2.wait(),notify(), notifyAll()

只能用在同步代码块或者方法中 lock不能用

并且调用者必须是同步监视器

这三个方法是定义在对象Object中的 所以都可以用对象调

3.sleep() 和wait()区别

相同点:都可以使得当前线程进入阻塞状态

不同点: 1) Thread类中声明Sleep() ,Object类中声明Wait()

​ 2) sleep()不会释放锁,wait() 会

​ 3.)sleep ()在任何场景都可调用,wait只能在同步代码中调用

8.测试题 1.存钱 ,两个人 公用一个账户,各村三次 每次1000 方法一:

package com.qyl.springboot.controller;public class AccountTest { public static void main(String[] args) { //定义初始化的账户 Account account = new Account(1000); //声明两个对象 去开线程 Customer c1 = new Customer(account); Customer c2 = new Customer(account); c1.setName("甲"); c2.setName("乙"); c1.start(); c2.start(); }}class Account { //声明账户余额 private double balance; //构造器 public Account(double balance) { this.balance = balance; } //往里面存钱的方法 //加synchronize 同步 public synchronized void cunQian (double atm){ if ((atm>0)){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("当前余额: "+balance); balance += atm; System.out.println(Thread.currentThread().getName()+" : 存了 "+atm+" 元,已到账.当前余额为"+balance+"员"); } }}//用户类,继承Threadclass Customer extends Thread{ //注入 Account private Account account; //构造器 public Customer(Account account) { this.account = account; } //子类重写父类Run方法 @Override public void run() { for (int i = 0; i < 3; i++) { //调用存钱方法 account.cunQian(1000); } }}

方法二:

package com.qyl.springboot.javaTest;public class CustomerQyl extends Thread{ private AccountQyl accountQyl; public CustomerQyl(AccountQyl accountQyl) { this.accountQyl = accountQyl; } @Override public void run() { for (int i = 0; i < 4; i++) { String s = accountQyl.Pay(1000); System.out.println(Thread.currentThread().getName()+" *** "+s); } }}

package com.qyl.springboot.javaTest;public class AccountQyl { private double balance; public AccountQyl(double balance) { this.balance = balance; } public synchronized String Pay (double atm){ if (atm>0){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("当前余额: "+balance); balance += atm; System.out.println(Thread.currentThread().getName()+" : 存了 "+atm+" 元,已到账.当前余额为"+balance+"员"); } return "存钱成功"; }}

package com.qyl.springboot.javaTest;public class testSync { public static void main(String[] args) { AccountQyl accountQyl = new AccountQyl(300); CustomerQyl c1 = new CustomerQyl(accountQyl); CustomerQyl c2 = new CustomerQyl(accountQyl); c1.setName("甲"); c2.setName("乙"); c1.start(); c2.start(); }}

2.java 递归

package com.esint.jm.wx_hxpublic.util;//递归 汉诺塔public class QylDiGuiTest { static int times = 0; public static void move (int num , char source , char dest){ System.out.println("第"+(++times)+"步骤 "+num +" 号盘子从 "+source+" 柱子到 "+dest+"柱子"); } public static void hnt (int n,char source,char mid,char dest){ if (1 == n){ move(n,source,dest); }else { hnt(n-1,source,dest,mid); move(n,source,dest); hnt(n-1,mid,source,dest); } } public static void main(String[] args) { hnt(5,'A','B','C'); }}

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。