Java中的线程

进程和线程概念 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。进程是线程的容器。 线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程中可以并发多个线程,每条线程并行执行不同的任务。 同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。 一个进程可以有很多线程,每条线程并行执行不同的任务。 线程 在 Java程序中,有两种方法创建线程: 一继承Thread重写run方法 二是通过实现Runnable接口,实现run方法 线程总体分两类:用户线程和守候线程。 当所有用户线程执行完毕的时候,JVM自动关闭。但是守候线程却不独立于JVM,守候线程一般是由操作系统或者用户自己创建的。 继承Thread public class ThreadOne extends Thread{ private String name; public ThreadOne() { } public ThreadOne(String name) { this.name = name; } @Override public void run() { for(int i=1;i<=10;i++){ System.out.println(name+"----"+i); } } } public class ThreadTest { public static void main(String[] args) { ThreadOne threadOne1 = new ThreadOne("地瓜"); ThreadOne threadOne2 = new ThreadOne("土豆"); threadOne1.start(); threadOne2.start(); } } 实现Runnable接口 public class ThreadTwo implements Runnable { private String name; public ThreadTwo() { } public ThreadTwo(String name) { this.name = name; } @Override public void run() { for(int i=1;i<=10;i++){ System.out.println(name+"-------"+i); } } } public class ThreadTest { public static void main(String[] args) { Thread t1 = new Thread(new ThreadTwo("地瓜")); Thread t2 = new Thread(new ThreadTwo("土豆")); t1.start(); t2.start(); } } 线程的转换 新建状态:线程对象已经创建 就绪状态:执行了start 运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。 阻塞:线程仍旧是活的,但是当前没有条件运行。 死亡态:当线程的run()方法完成时就认为它死去。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦死亡,就不能复生。如果在一个死去的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。 ...

July 24, 2019 · 1 min · zhangxiaofeng05

Spring Boot打印日志

本文环境 jdk 1.8 maven 3.6.1 Spring Boot 2.1.6 SLF4J 为什么要介绍SLF4J? SLF4J是一个接口,log4j和logback是它的实现。 SLF4J官网:https://www.slf4j.org 官网示例 引入jar包 slf4j-api-1.7.26.jar slf4j-simple-1.7.26.jar 编写测试类(Java Project) import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HelloWorld { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger(HelloWorld.class); logger.info("Hello World"); } } 有什么问题,去官网查看示例! Spring Boot中使用日志(logback) 编写测试类 import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class LogbackTest { //记录器 Logger logger = LoggerFactory.getLogger(getClass()); @Test public void logTest() { //日志的级别 //从上到下---由低到高 //日志会在设置的级别和高级别生效,Spring Boot默认info logger.trace("这是trace日志..."); logger.debug("这是debug日志..."); //可以在logback-spring.xml或者在application.xml配置日志级别 logger.info("这是info日志..."); logger.warn("这是warn日志..."); logger.error("这是error日志..."); } } 设置日志的格式 resources/logback-spring.xml <?xml version="1.0" encoding="UTF-8"?> <configuration debug="false" scan="true" scanPeriod="60 seconds"> <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 --> <!-- <property name="LOG_PATH" value="/data/log/process/springboot-demo" /> --> <springProperty name="LOG_PATH" source="logging.path" defaultValue="../logs" /> <!-- 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!-- 按照每天生成日志文件 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--日志文件输出的文件名 --> <FileNamePattern>${LOG_PATH}/log.log.%d{yyyy-MM-dd}</FileNamePattern> <!--日志文件保留天数 --> <!-- <MaxHistory>30</MaxHistory> --> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!-- 日志输出级别 --> <root level="INFO"> <appender-ref ref="FILE" /> <appender-ref ref="STDOUT" /> </root> </configuration> 配置文件的加载顺序 application.properties或者application.yml文件作为Spring Boot的默认配置文件 ...

July 20, 2019 · 1 min · zhangxiaofeng05

Spring Boot发送邮件

本文环境 jdk 1.8 maven 3.6.1 Spring Boot 2.1.6 引入依赖 pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> 在application.properties中添加邮件配置(以QQ邮箱为例) spring.mail.host=smtp.qq.com spring.mail.port=587 spring.mail.username=xxx@qq.com spring.mail.password=授权码 spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.starttls.required=true spring.mail.default-encoding=UTF-8 mail.fromMail.addr=xxx@qq.com #发送来源,和账户相同 QQ邮箱的服务器端口 接收邮件服务器:imap.qq.com,使用SSL,端口号993 发送邮件服务器:smtp.qq.com,使用SSL,端口号465或587 QQ邮箱帮助中心 编写Service接口 public interface MailService { public void sendSimpleMail(String to,String subject,String content); public void sendHtmlMail(String to, String subject, String content); public void sendAttachmentsMail(String to, String subject, String content, String filePath); } } 编写Service的实现类 import java.io.File; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.FileSystemResource; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; @Component public class MailServiceImpl implements MailService{ private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private JavaMailSender mailSender; @Value("${mail.fromMail.addr}") private String from; @Override public void sendSimpleMail(String to, String subject, String content) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(from); message.setTo(to); message.setSubject(subject); message.setText(content); try { mailSender.send(message); logger.info("简单邮件已经发送"); } catch (Exception e) { logger.error("发送简单邮件时发生异常!",e); } } @Override public void sendHtmlMail(String to, String subject, String content) { MimeMessage message = mailSender.createMimeMessage(); try { //true表示需要创建一个multipart message MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); helper.setText(content, true); mailSender.send(message); logger.info("html邮件发送成功"); } catch (MessagingException e) { logger.error("发送html邮件时发生异常!", e); } } @Override public void sendAttachmentsMail(String to, String subject, String content, String filePath) { MimeMessage message = mailSender.createMimeMessage(); try { MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); helper.setText(content, true); FileSystemResource file = new FileSystemResource(new File(filePath)); String fileName = filePath.substring(filePath.lastIndexOf(File.separator)); helper.addAttachment(fileName, file); mailSender.send(message); logger.info("带附件的邮件已经发送。"); } catch (MessagingException e) { logger.error("发送带附件的邮件时发生异常!", e); } } } 编写测试类 import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import com.boot.service.MailService; @RunWith(SpringRunner.class) @SpringBootTest public class MailTest { @Autowired private MailService mailService; @Test public void testSimple() { mailService.sendSimpleMail("xxx@163.com", "test simple mail", "hello this is simple mail"); } @Test public void testHtmlMail() throws Exception { String content="<html>\n" + "<body>\n" + " <h3>hello world ! 这是一封Html邮件!</h3>\n" + "</body>\n" + "</html>"; mailService.sendHtmlMail("xxx@163.com","test simple mail",content); } @Test public void sendAttachmentsMail() { String filePath="D:\\testMail.txt"; mailService.sendAttachmentsMail("xxx@163.com", "主题:带附件的邮件", "有附件,请查收!", filePath); } } 至此,邮件发送成功! ...

July 19, 2019 · 2 min · zhangxiaofeng05

request和Session

区别 request session 描述 一次请求(访问一个url) 一次对话(可以访问多个url) 作用 获取信息(表单,查询,cookie等信息) 记录变量(跟踪记录访问者动作) 作用端 浏览器 服务器 生命周期 提交以后即释放 关闭浏览器或者超出会话时间限制(maxInactiveIntervalInSeconds;The session timeout in seconds. By default, it is set to 1800 seconds (30 minutes).) 占用资源 比较少 相对较大 安全性 比较高 稍微低点

July 19, 2019 · 1 min · zhangxiaofeng05

Druid数据库连接池

阿里巴巴数据库事业部出品,为监控而生的数据库连接池。 托管于GitHub,项目地址 https://github.com/alibaba/druid Druid是一个JDBC组件库,包括数据库连接池、SQL Parser等组件。DruidDataSource是最好的数据库连接池。 Springboot使用 最新信息去GitHub Maven <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.17</version> </dependency> Gradle compile 'com.alibaba:druid-spring-boot-starter:1.1.17' 配置 Github上有说明,下面是一下常用配置 application.properties #mysql spring.datasource.platform=mysql spring.datasource.url=jdbc:mysql://localhost:3306/database?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=154704 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #druid spring.datasource.type=com.alibaba.druid.pool.DruidDataSource # Advanced configuration... spring.datasource.max-active=500 spring.datasource.min-idle=2 spring.datasource.initial-size=6 开启监测 DruidConfiguration 监测地址:http://localhost:8080/druid/index.html import javax.sql.DataSource; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; @Configuration public class DruidConfiguration { @ConfigurationProperties("spring.datasource") @Bean public DataSource druidDataSource() { return new DruidDataSource(); } @Bean public ServletRegistrationBean<StatViewServlet> druidStatViewServlet() { ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); registrationBean.addInitParameter("allow", "127.0.0.1");// IP白名单 (没有配置或者为空,则允许所有访问) registrationBean.addInitParameter("deny", "");// IP黑名单 (存在共同时,deny优先于allow) registrationBean.addInitParameter("loginUsername", "root"); registrationBean.addInitParameter("loginPassword", "123456"); registrationBean.addInitParameter("resetEnable", "false"); return registrationBean; } } 测试类 import java.sql.Connection; import javax.sql.DataSource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringbootApplicationTests { @Autowired DataSource dataSource; @Test public void contextLoads() { } @Test public void test1() throws Exception { System.out.println(dataSource.getClass()); Connection connection = dataSource.getConnection(); System.out.println(connection.getClass()); connection.close(); } }

July 18, 2019 · 1 min · zhangxiaofeng05

Object类

特点 是Java中唯一一个没有父类的类 java中所有的类不是object类的直接子类,就是其间接子类 定义在object类中的所有方法,在任何类中都可以直接调用,而不需要声明object类的对象。 是java中所有类的超类(基类 ,父类) object类中只有无参构造 方法 常用方法 public boolean equals(object obj) public boolean equals(Object obj) { return (this == obj); } 指示其他某个对象是否与此对象“相等”。 (ps:==判断是否引用地址相同) 2. public String tostring() 返回对象的字符串表示形式。 3. public int hashCode() 返回此对象的一个哈希码值。 不常用方法 protected Object clone() 创建并返回此对象的一个副本。 protected void finalize() 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。子类重写 finalize 方法,以配置系统资源或执行其他清除。 public final Class<?> getClass() 返回此 Object 的运行时类。 public final void notify() 唤醒在此对象监视器上等待的单个线程。 public final void notifyAll() 唤醒在此对象监视器上等待的所有线程。 public final void wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 public final void wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。 public final void wait(long timeout,int nanos) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。

July 18, 2019 · 1 min · zhangxiaofeng05

数据库隔离级别和传播行为

事务五个隔离级别 DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 . READ_UNCOMMITTED 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 ) READ_COMMITTED 会出现不可重复读、幻读问题(锁定正在读取的行) REPEATABLE_READ 会出幻读(锁定所读取的所有行) SERIALIZABLE 保证所有的情况不会发生(锁表) spring中七个事务传播行为 在TransactionDefinition接口中定义了七个事务传播行为。 PROPAGATION_REQUIRED(默认的spring事务传播级别) 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。 PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。 PROPAGATION_REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。 PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。 PROPAGATION_NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常 PROPAGATION_NESTED 如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

July 18, 2019 · 1 min · zhangxiaofeng05

悲观锁和乐观锁

悲观锁和乐观锁:处理的是同一张表的同一行记录 悲观锁 如果使用了(加了一个行锁),如果事务没有被释放,就会造成其他事务处于等待。 使用数据库提供的锁机制实现悲观锁。 如果数据库不支持设置的锁机制,JPA会使用该数据库提供的合适的锁机制来完成,而不会报错。 使用entityManage.find(class,id,LockModeType);加悲观锁,相当于发送SELECT … FOR UPDATE 使用entityManage.lock(object,LockModeType);加悲观锁,相当于发送SELECT id FROM … FOR UPDATE 乐观锁(性能好) 添加一个私有字段version,不由程序员维护,由JPA自己维护 @Version private long version;

July 17, 2019 · 1 min · zhangxiaofeng05

什么是面向接口编程

面向接口编程 要正确地使用Java语言进行面向对象的编程,从而提高程序的复用性,增加程序的可维护性、可扩展性,就必须是面向接口的编程。面向接口的编程就意味着:开发系统时,主体构架使用接口,接口构成系统的骨架。这样就可以通过更换实现接口的类来更换系统的实现。 示例 public interface Person { public void show(); } public class Man implements Person{ @Override public void show() { System.out.println("Man...的show方法执行了。。。。"); } } public class Woman implements Person{ @Override public void show() { System.out.println("Woman...中的show方法执行了。。。。"); } } public class MainTest { public void show(Person person) { person.show(); } public static void main(String[] args) { Person man = new Man();//选择Persion,而不是Man man = new Man(); Person woman = new Woman();//选择Persion,而不是Woman woman = new Woman(); man.show(); woman.show(); System.out.println("-----------------"); MainTest test = new MainTest(); test.show(man); test.show(woman); System.out.println(man instanceof Woman); System.out.println(man instanceof Person); System.out.println(woman instanceof Person); } } 执行结果: ...

July 15, 2019 · 1 min · zhangxiaofeng05

linux安装QQ

首先要感谢deepin,QQ很早就停止linux版的更新了,deepin团队在移植上的力度还是比较大的。以后有机会的话,还会再装deepin的。 也要感谢wszqkzqk,做了整理。 解决方案 GitHub:https://github.com/wszqkzqk/deepin-wine-ubuntu 你也可以看作者的README,但是我没看,作者写的比较精简,有些具体的没看懂怎么操作!!原谅我是个萌新。 第一步:安装deepin-wine环境 上https://github.com/wszqkzqk/deepin-wine-ubuntu页面下载zip包(或用git方式克隆),解压到本地文件夹 在中国推荐用下面的地址,速度更快: (git clone https://gitee.com/wszqkzqk/deepin-wine-for-ubuntu.git) 在文件夹中打开终端,输入sudo sh ./install.sh一键安装。 第2步,安装相关应用容器 在http://mirrors.aliyun.com/deepin/pool/non-free/d/中下载想要的容器,点击deb安装即可。 (建议在终端下使用dpkg -i安装容器,否则容易误报依赖错误) 第3步,关于托盘 安装TopIconPlus的gnome-shell扩展,命令:sudo apt-get install gnome-shell-extension-top-icons-plus gnome-tweaks,然后用r命令重启gnome-shell(Alt+F2,输入r),最后用gnome-tweaks开启这个扩展。 参考 https://www.lulinux.com/archives/1319 https://github.com/wszqkzqk/deepin-wine-ubuntu

April 30, 2019 · 1 min · zhangxiaofeng05