在这篇文章中,我们将为您详细介绍Java复习的内容,并且讨论关于十三----多线程的相关问题。此外,我们还会涉及一些关于-1-5java多线程概念进程线程区别联系java创建线程方式线程组线程池概念线
在这篇文章中,我们将为您详细介绍Java 复习的内容,并且讨论关于十三---- 多线程的相关问题。此外,我们还会涉及一些关于-1-5 java 多线程 概念 进程 线程区别联系 java 创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock 锁 sleep () 和 wait () 方法的区别 为什么 wait...、0005--java 多线程、AG 百家乐最新官网《 787977.tv 蝙蝠 14735340 》java 并发编程 (2):Java 多线程 - java.util.concurrent 高级工具、java 中的日期类型:java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp 区别和总结的知识,以帮助您更全面地了解这个主题。
本文目录一览:- Java 复习(十三)---- 多线程(三)(java 多线程实战)
- -1-5 java 多线程 概念 进程 线程区别联系 java 创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock 锁 sleep () 和 wait () 方法的区别 为什么 wait...
- 0005--java 多线程
- AG 百家乐最新官网《 787977.tv 蝙蝠 14735340 》java 并发编程 (2):Java 多线程 - java.util.concurrent 高级工具
- java 中的日期类型:java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp 区别和总结
Java 复习(十三)---- 多线程(三)(java 多线程实战)
生产者消费者问题
现在我们要写一个程序,来模拟做馒头和吃馒头,一个不断的往篮子里扔做熟的馒头,一个不断的在那吃。模型如下:
现在要求是,写一个程序来模拟这个过程,面向对象,怎么写呢?
我们要写考虑里面有哪些类呢?我们分析名字就行了
首先我们先把主要的类和 main 方法写一下:
public class ProducerConsumer {
public static void main(String[] args) {
}
}
然后写一下馒头类:
class WoTou {
int id;
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou : " + id;
}
}
给他一个 id,可以更好地看清哪个馒头做出来了,那个馒头被吃了。
接下来是篮子类。我们想一下,我们先做的馒头是放在底层的是吧,别人要吃都是从上面开始拿的,先进后出
,栈。
class SyncStack {
int index = 0;//装到第几个了
WoTou[] arrWT = new WoTou[6];//这个篮子能装6个馒头
//装馒头的方法
public synchronized void push(WoTou wt) {
arrWT[index] = wt;
index ++;//放了馒头,肯定要占一个位置的
}
要是上面程序不加锁会怎样呢?
当你在一个位置装了馒头之后,有另外一个线程,放馒头的人也好,吃馒头的人也好,都是一个线程。你往里扔馒头的时候,有一个人已经扔进去了,可是他被打断了,index还没来得及往上加
,下一个人又往里扔,会产生什么问题啊,会把原来的馒头给覆盖掉。index 还是 0。怎么解决呢?加个锁就好了!
还有一个问题就是,如果篮子满了怎么办呢?我们是不是得休息一下啊。所以要进行线程控制,用 wait方法
:
public synchronized void push(WoTou wt) {
while(index == arrWT.length) {
try {
this.wait();//指的是SyncStack,让生产者休息
} catch (InterruptedException e) {
e.printStackTrace();
}
}
arrWT[index] = wt;
index ++;
}
wait
的解释是,当前的,正在我这个对象访问的线程。
一个线程访问 push () 方法的时候,他已经拿到这个对象的锁了,拿到对象这个锁的线程,在执行的过程之中,他遇见一个事件必须阻塞住,必须停止。什么事件,已经满了,你不能往里填了。必须等清洁工把它清走,才可以继续。没清走之前,你只能等着
。
这里我们说一下 wait 和 sleep 的区别:
上面代码是不行的,为什么不行呢,因为这个东西全等在那了,第一个人生产满了,他就在那等住了,等住了之后,另外一个人就算消费空了,篮子里边没有馒头了,可是他依然运行不了。为什么呀?因为
没有人叫醒他
。
wait 时别的线程可以访问锁定对象。调用 wait 方法的时候必须锁定该对象。
sleep 时别的线程也不可以访问锁定对象
wait 和 sleep 不一样。sleep 过一段时间他会自己醒过来,可是 wait 不行。wait 一旦 wait 过去,对不起,死过去了。并且,wait一旦wait过去了,这个对象的锁不在归我所有,只有醒过来的时候才会再去找这把锁
。这是 wait 和 sleep 之间巨大的区别。wait 的时候,锁不在归我所有。sleep 的时候,睡着了也得抱着那把锁。
wait 完之后我们要干嘛呢?我们要做一件事,就是叫消费者赶快消费是吧,这样篮子才会有空位置。这时我们就要用 notify 方法了。wait方法和notify方法是一一对应的。
所以我们就得在代码中加上 this.notify()。当有多个线程就得用this.notiyAll()
notify 的含义:叫醒一个正在 wait 在我这个对象上的线程。this.notify (),谁现在正在我这个对象等待着,我就叫醒谁,让它继续执行
那我们既然有放馒头的方法,肯定也有拿馒头的方法是吧:
public synchronized WoTou pop() {
index--;//拿了馒头,便把位置数-1
return arrWT[index];
}
pop 方法也一样,当篮子里的馒头空了之后,就必须等待着
public synchronized WoTou pop() {
while(index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
index--;
return arrWT[index];
}
接下来我们还得有生产者这个类吧,不然馒头哪里来?他是一个线程,因为好多人在一起做馒头。
class Producer implements Runnable {
SyncStack ss = null;//生产者得知道往哪个框生产吧,所以得引用一个对象。
Producer(SyncStack ss) {
this.ss = ss;
}
有了线程,就得有启动线程的方法
public void run() {
for(int i=0; i<20; i++) {
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("生产了:" + wt);
try {
Thread.sleep((int)(Math.random() * 1000));
//为了方便观察,每生产一个,便睡眠一会
//Math.random()是一个double类型,这里强制转换为int类型
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
有生产者的类,自然也就有消费者的类:
class Consumer implements Runnable {
SyncStack ss = null;
Consumer(SyncStack ss) {
this.ss = ss;
}
}
消费者这个线程自然也有启动的方法:
public void run() {
for(int i=0; i<20; i++) {
WoTou wt = ss.pop();
System.out.println("消费了: " + wt);
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
接下来我们就得模拟一下线程了。首先得造一个框出来装馒头吧。
public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p = new Producer(ss);
Consumer c = new Consumer(ss);
new Thread(p).start();
new Thread(c).start();
}
}
这里只模拟了一个生产者和一个消费者。
下面来看看完整代码:
package Thread;
public class ProducerConsumer {
public static void main(String[] args) {
SyncStack ss = new SyncStack();
Producer p = new Producer(ss);
Consumer c = new Consumer(ss);
new Thread(p).start();
new Thread(p).start();
new Thread(c).start();
new Thread(c).start();
}
}
class WoTou {
int id;
WoTou(int id) {
this.id = id;
}
public String toString() {
return "WoTou : " + id;
}
}
class SyncStack {
int index = 0;
WoTou[] arrWT = new WoTou[6];
public synchronized void push(WoTou wt) {
while(index == arrWT.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
arrWT[index] = wt;
index ++;
}
public synchronized WoTou pop() {
while(index == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
index--;
return arrWT[index];
}
}
class Producer implements Runnable {
SyncStack ss = null;
Producer(SyncStack ss) {
this.ss = ss;
}
public void run() {
for(int i=0; i<20; i++) {
WoTou wt = new WoTou(i);
ss.push(wt);
System.out.println("生产了:" + wt);
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
SyncStack ss = null;
Consumer(SyncStack ss) {
this.ss = ss;
}
public void run() {
for(int i=0; i<20; i++) {
WoTou wt = ss.pop();
System.out.println("消费了: " + wt);
try {
Thread.sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
多线程(三)也写到这啦,这个章节比较简单,就说了一下生产者和消费者的问题,也说了 wait 和 sleep 的区别,这个是重点!
-1-5 java 多线程 概念 进程 线程区别联系 java 创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock 锁 sleep () 和 wait () 方法的区别 为什么 wait...
多线程
Java 程序运行原理
创建线程方式一
继承 Thread 类
1. 子类覆盖父类中的 run 方法,将线程运行的代码存放在 run 中。2. 建立子类对象的同时线程也被创建。3. 通过调用 start 方法开启线程。
创建线程方式二
实现 Runnable 接口
1. 子类覆盖接口中的 run 方法。2. 通过 Thread 类创建线程,并将实现了 Runnable 接口的子类对象作为参数传递给 Thread 类的构造函数。3.Thread 类对象调用 start 方法开启线程。
线程的调度和优先级
线程的控制方法
sleep () 和 wait () 方法的区别
解决线程安全问题的基本思想
同步
synchronized (对象){需要同步的代码;}
Lock•void lock()•void unlock()ReentrantLock
线程组
线程池
匿名内部类方式使用多线程
定时器
线程类的其他方法
setPriority(int num)setDaemon(boolean b)join()自定义线程名称toString()
0005--java 多线程
0005--java 多线程
AG 百家乐最新官网《 787977.tv 蝙蝠 14735340 》java 并发编程 (2):Java 多线程 - java.util.concurrent 高级工具
高级多线程控制类
Java1.5 提供了一个非常高效实用的多线程包:java.util.concurrent, 提供了大量高级工具,可以帮助开发者编写高效、易维护、结构清晰的 Java 多线程程序。
ThreadLocal 类
ThreadLocal 类 用来保存线程的独立变量。对一个线程类(继承自 Thread)
当使用 ThreadLocal 维护变量时,ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。常用于用户登录控制,如记录 session 信息。
实现:每个 Thread 都持有一个 TreadLocalMap 类型的变量(该类是一个轻量级的 Map,功能与 map 一样,区别是桶里放的是 entry 而不是 entry 的链表。功能还是一个 map。)以本身为 key,以目标为 value。
主要方法是 get () 和 set (T a),set 之后在 map 里维护一个 threadLocal -> a,get 时将 a 返回。ThreadLocal 是一个特殊的容器。
原子类(AtomicInteger、AtomicBoolean……)
如果使用 atomic wrapper class 如 atomicInteger,或者使用自己保证原子的操作,则等同于 synchronized
AtomicInteger.compareAndSet (int expect,int update)// 返回值为 boolean
AtomicReference
对于 AtomicReference 来讲,也许对象会出现,属性丢失的情况,即 oldObject == current,但是 oldObject.getPropertyA != current.getPropertyA。
这时候,AtomicStampedReference 就派上用场了。这也是一个很常用的思路,即加上版本号
Lock 类
lock: 在 java.util.concurrent 包内。共有三个实现:
- ReentrantLock
- ReentrantReadWriteLock.ReadLock
- ReentrantReadWriteLock.WriteLock
主要目的是和 synchronized 一样, 两者都是为了解决同步问题,处理资源争端而产生的技术。功能类似但有一些区别。
区别如下:
- lock 更灵活,可以自由定义多把锁的枷锁解锁顺序(synchronized 要按照先加的后解顺序)
- 提供多种加锁方案,lock 阻塞式,trylock 无阻塞式,lockInterruptily 可打断式, 还有 trylock 的带超时时间版本。
- 本质上和监视器锁(即 synchronized 是一样的)
- 能力越大,责任越大,必须控制好加锁和解锁,否则会导致灾难。
- 和 Condition 类的结合。
- 性能更高,synchronized 和 Lock 性能对比,如下图:
ReentrantLock 的使用
可重入的意义在于持有锁的线程可以继续持有,并且要释放对等的次数后才真正释放该锁。
private java.util.concurrent.locks.Lock lock = new ReentrantLock();
public void method() {
try {
lock.lock(); //获取到锁lock,同步块
} finally {
lock.unlock();//释放锁lock
}
}
复制
- ReentrantLock 比 synchronized 功能更强大,主要体现:
- ReentrantLock 具有公平策略的选择。
- ReentrantLock 可以在获取锁的时候,可有条件性地获取,可以设置等待时间,很有效地避免死锁。
- 如 tryLock () 和 tryLock (long timeout, TimeUnit unit)
- ReentrantLock 可以获取锁的各种信息,用于监控锁的各种状态。
- ReentrantLock 可以灵活实现多路通知,即 Condition 的运用。
公平锁与非公平锁
ReentrantLock 默认是非公平锁,允许线程 “抢占插队” 获取锁。公平锁则是线程依照请求的顺序获取锁,近似 FIFO 的策略方式。
锁的使用
- lock () 阻塞式地获取锁,只有在获取到锁后才处理 interrupt 信息
- lockInterruptibly () 阻塞式地获取锁,立即处理 interrupt 信息,并抛出异常
- tryLock () 尝试获取锁,不管成功失败,都立即返回 true、false,注意的是即使已将此锁设置为使用公平排序策略,tryLock () 仍然可以打开公平性去插队抢占。如果希望遵守此锁的公平设置,则使用 tryLock (0, TimeUnit.SECONDS),它几乎是等效的 (也检测中断)。
- tryLock (long timeout, TimeUnit unit) 在 timeout 时间内阻塞式地获取锁,成功返回 true,超时返回 false,同时立即处理 interrupt 信息,并抛出异常。
如果想使用一个允许闯入公平锁的定时 tryLock,那么可以将定时形式和不定时形式组合在一起:
if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
private java.util.concurrent.locks.ReentrantLock lock = new ReentrantLock();
public void testMethod() {
try {
if (lock.tryLock(1, TimeUnit.SECONDS)) {
//获取到锁lock,同步块
} else {
//没有获取到锁lock
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread())
//如果当前线程持有锁lock,则释放锁lock
lock.unlock();
}
}
复制
条件 Condition 的使用
条件 Condition 可以由锁 lock 来创建,实现多路通知的机制。
具有 await、signal、signalAll 的方法,与 wait/notify 类似,需要在获取锁后方能调用。
private final java.util.concurrent.locks.Lock lock = new ReentrantLock();
private final java.util.concurrent.locks.Condition condition = lock.newCondition();
public void await() {
try {
lock.lock(); //获取到锁lock
condition.await();//等待condition通信信号,释放condition锁
//接到condition通信
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();//释放对象锁lock
}
}
复制
ReentrantReadWriteLock 的使用
ReentrantReadWriteLock 是对 ReentrantLock 更进一步的扩展,实现了读锁 readLock ()(共享锁) 和写锁 writeLock ()(独占锁),实现读写分离。读和读之间不会互斥,读和写、写和读、写和写之间才会互斥,提升了读写的性能。
读锁示例:
private final java.util.concurrent.locks.ReadWriteLock lock = new ReentrantReadWriteLock();
public void method() {
try {
lock.readLock().lock();//获取到读锁readLock,同步块
} finally {
lock.readLock().unlock();//释放读锁readLock
}
}
复制
写锁示例:
private final java.util.concurrent.locks.ReadWriteLock lock = new ReentrantReadWriteLock();
public void method() {
try {
lock.writeLock().lock(); //获取到写锁writeLock,同步块
} finally {
lock.writeLock().unlock(); //释放写锁writeLock
}
}
复制
容器类
同步容器与异步容器概览
同步容器
包括两部分:
- 一个是早期 JDK 的 Vector、Hashtable;
- 一个是它们的同系容器,JDK1.2 加入的同步包装类,使用 Collections.synchronizedXxx 工厂方法创建。
Map<String, Integer> hashmapSync = Collections.synchronizedMap(new HashMap<>());
同步容器都是线程安全的,一次只有一个线程访问容器的状态。
但在某些场景下可能需要加锁来保护复合操作。
复合类操作如:新增、删除、迭代、跳转以及条件运算。
这些复合操作在多线程并发的修改容器时,可能会表现出意外的行为,
最经典的便是 ConcurrentModificationException,
原因是当容器迭代的过程中,被并发的修改了内容,这是由于早期迭代器设计的时候并没有考虑并发修改的问题。
其底层的机制无非就是用传统的 synchronized 关键字对每个公用的方法都进行同步,使得每次只能有一个线程访问容器的状态。这很明显不满足我们今天互联网时代高并发的需求,在保证线程安全的同时,也必须有足够好的性能。
并发容器
与 Collections.synchronizedXxx () 同步容器等相比,util.concurrent 中引入的并发容器主要解决了两个问题:
- 根据具体场景进行设计,尽量避免 synchronized,提供并发性。
- 定义了一些并发安全的复合操作,并且保证并发环境下的迭代操作不会出错。
util.concurrent 中容器在迭代时,可以不封装在 synchronized 中,可以保证不抛异常,但是未必每次看到的都是 "最新的、当前的" 数据。
Map<String, Integer> concurrentHashMap = new ConcurrentHashMap<>();
ConcurrentHashMap 替代同步的 Map 即 (Collections.synchronized (new HashMap ()))。
众所周知,HashMap 是根据散列值分段存储的,同步 Map 在同步的时候会锁住整个 Map,而 ConcurrentHashMap 在设计存储的时候引入了段落 Segment 定义,同步的时候只需要锁住根据散列值锁住了散列值所在的段落即可,大幅度提升了性能。ConcurrentHashMap 也增加了对常用复合操作的支持,比如 "若没有则添加":putIfAbsent (),替换:replace ()。这 2 个操作都是原子操作。注意的是 ConcurrentHashMap 弱化了 size () 和 isEmpty () 方法,并发情况尽量少用,避免导致可能的加锁 (当然也可能不加锁获得值,如果 map 数量没有变化的话)。 CopyOnWriteArrayList 和 CopyOnWriteArraySet 分别代替 List 和 Set,主要是在遍历操作为主的情况下来代替同步的 List 和同步的 Set,这也就是上面所述的思路:迭代过程要保证不出错,除了加锁,另外一种方法就是 "克隆" 容器对象。--- 缺点也明显,占有内存,且数据最终一致,但数据实时不一定一致,一般用于读多写少的并发场景。
- ConcurrentSkipListMap 可以在高效并发中替代 SoredMap (例如用 Collections.synchronzedMap 包装的 TreeMap)。
- ConcurrentSkipListSet 可以在高效并发中替代 SoredSet (例如用 Collections.synchronzedSet 包装的 TreeMap)。
- ConcurrentLinkedQuerue 是一个先进先出的队列。它是非阻塞队列。注意尽量用 isEmpty,而不是 size ();
CountDownLatch 闭锁的使用
管理类
管理类的概念比较泛,用于管理线程,本身不是多线程的,但提供了一些机制来利用上述的工具做一些封装。
了解到的值得一提的管理类:ThreadPoolExecutor 和 JMX 框架下的系统级管理类 ThreadMXBean
ThreadPoolExecutor
如果不了解这个类,应该了解前面提到的 ExecutorService,开一个自己的线程池非常方便:
ExecutorService e = Executors.newCachedThreadPool();
ExecutorService e = Executors.newSingleThreadExecutor();
ExecutorService e = Executors.newFixedThreadPool(3);
// 第一种是可变大小线程池,按照任务数来分配线程,
// 第二种是单线程池,相当于FixedThreadPool(1)
// 第三种是固定大小线程池。
// 然后运行
e.execute(new MyRunnableImpl());
复制
该类内部是通过 ThreadPoolExecutor 实现的,掌握该类有助于理解线程池的管理,本质上,他们都是 ThreadPoolExecutor 类的各种实现版本。
参考文章:
Java 多线程并发编程一览笔录 https://www.cnblogs.com/yw0219/p/10597041.html
Java 中的多线程你只要看这一篇就够了 https://juejin.im/entry/57339fe82e958a0066bf284f
java 中的日期类型:java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp 区别和总结
在 web 开发中,避免不了对日期的操作,就几种常见的日期操作做个总结 (部分参考网络,在此表示感谢):
java.util.Date、Java.util.Calendar、java.sql.Date、java.sql.Time、java.sql.Timestamp
java.lang.Object
....|__java.util.Date
..........|__java.sql.Date/java.sql.Timestamp /java.sql.Time
....|__java.security.Timestamp
java.util.Date 日期格式为:年月日时分秒
java.sql.Date 日期格式为:年月日 [只存储日期数据不存储时间数据]
java.sql.Time 日期格式为:时分秒
java.sql.Timestamp 日期格式为:年月日时分秒纳秒(毫微秒)
关系:
java.util.Date 这个类是 java.sql.Date, java.sql.Time, java.slq.Timestamp 这三个类的父类。这三个类对 java.util.Date 类进行了包装。
联系:
java.sql.Date 类屏蔽了 java.util.Date 类的时间有关的方法(形如:hh:mm:ss), 因此,不可以通过这个类访问时间有关的信息,比如,如果你通过 sqlDate.getHour () 方法去访问小时信息,此方法会抛出一个 IllegalArgumentException
异常。这是因为java.sql.Date在继承java.util.Date类的时候对父类进行了重写,禁用了时间访问的方法。之所以这么处理,是为了和数据库的Date数据类型相匹配,数据库的Date数据类行只是保存日期有关的字段。
Java.sql.Time 类屏蔽了 java.util.Date 的日期有关的字段(形如:yyyy-MM-dd), 因此,不能通过这个类访问日期有关的信息,比如:如果你通过 sqlTime.getYear () 方法去获取年有关的信息,此方法会抛出一个 IllegalArgumentException
异常。这是因为java.sql.Time在继承java.util.Date类的时候对父类进行了重写,禁用了日期访问的方法。之所以这么处理,是为了和数据库的Time数据类型相匹配,数据库的Time数据类行只是保存时间有关的字段。
Java.sql.Timestamp
字段则对java.util.Date这个类进行了扩充,它在java.util.Date类的基础上增加了毫秒的时间访问控制,因此,你可以通过
getNanos()方法去获取时间的毫微秒数(注意此处获取的时间是以毫微秒为单位的,1 秒等于十亿毫微秒),同样的,这也是为了和数据库中的 Timestamp 数据类型进行匹配。
理清了上述四个类的关系,那么 java.util.Date 和 java.util.Calendar 类有什么关系呢?
Java.util.Calendar 类是 java.util.Date 类的一个更加深入,更加全面的替代。Java.util.Calendar 类支持 java.util.Date 的所有功能,此外,Calendar 还引入了多语言,多区域的特性,可以根据需要获取不同区域,不同时区的时间,Calendar 还增加了比 Date 更加方便和快捷的许多操作,如获取一年当中的第几个星期,各个月的天数等便捷的方法。
注意:
Java.util.Calendar 区别与 java.util.Date 的几个地方也需要注意一下:首先,Calendar 增加了毫秒的时间段,通过它可以获取时间点的毫秒值,而 java.util.Date 只是精确到秒。其次,Calendar 过去年的时候是当前年份比如:2010,而 Date 获取年份的时获取到的是当前年份 - 1900 的一个值(2010-1900=110,因此,你调用 getYear 后过去的值就是 110)。最后 Calendar 是一个抽象类,之所以能够实例化,是因为此处的 Calendar 充当了一个类似于工厂的作用,在 getInstance 方法中实例化了 Calendar 子类 GregorianCalendar,并把它返回给用户使用。
针对不同的数据库选用不同的日期类型
・Oracle 的 Date 类型,只需要年月日,选择使用 java.sql.Date 类型
・MS Sqlserver 数据库的 DateTime 类型,需要年月日时分秒,选择 java.sql.Timestamp 类型
String 日期格式转换成 Date 日期格式
//java.util.Date 时间格式的转换
SimpleDateFormat f_utilDate=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String str="2011-5-31 14:40:50";
try {
java.util.Date utilDate=f_utilDate.parse(str);
System.out.println(f_utilDate.format(utilDate));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//java.sql.Date 时间格式的转换
SimpleDateFormat f_sqlDate=new SimpleDateFormat("yyyy-MM-dd");
java.sql.Date sqlDate = java.sql.Date.valueOf("2010-08-20");
System.out.println(f_sqlDate.format(sqlDate));
//java.sql.Time sqltime 时间格式的转换
SimpleDateFormat f_sqlTime=new SimpleDateFormat("hh:mm:ss");
java.sql.Time sqltime = java.sql.Time.valueOf("13:44:53");
System.out.println(f_sqlTime.format(sqltime));
//java.sql.Timestamp 时间格式的转换
SimpleDateFormat f_timestamp=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
java.sql.Timestamp timestamp = java.sql.Timestamp.valueOf("2010-08-20 14:06:27.186");
System.out.println(f_timestamp.format(timestamp));
//java.util.Date 转换成 java.sql.Date 格式
try{
SimpleDateFormat DateFormate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
java.util.Date date1 = DateFormate.parse("2011-5-31 14:40:50");
java.sql.Date sqlDate = new java.sql.Date(date1.getTime());
System.out.println(DateFormate.format(sqlDate));
}catch (Exception ex) {
System.out.println(ex.getMessage());
}
//java.sql.Date 转换成 java.util.Date 格式
java.sql.Date sqlDate1=java.sql.Date.valueOf("2005-12-12");
java.util.Date utilDate1=new java.util.Date(sqlDate1.getTime());
System.out.println ("java.sql.Date 转换成 java.util.Date 格式:"+f.format (utilDate1));
//java.util.Date 转换 java.sql.Timestamp
new java.sql.Timestamp (new java.util.Date ().getTime ());// 此处 IDE 报错
//java.util.Date 转换 java.sql.Time
new java.sql.Time(new java.util.Date().getTime());
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
我们可以使用 DateFormat 处理字符串来定义时间日期的格式
注:String 都是先转换为 java.util.Date,然后再转换成所需的格式
try{
String dateString = "2010-08-20 12:00:00.125";
DateFormat dateFormat = new SimpleDateFormat ("yyyy-MM-dd kk:mm:ss.SSS",Locale.ENGLISH);// 设定格式
dateFormat.setLenient(false);
java.util.Date utilDate = dateFormat.parse (dateString);//util 类型
java.sql.Timestamp dateTime = new java.sql.Timestamp (utilDate.getTime ());//Timestamp 类型,timeDate.getTime () 返回一个 long 型
System.out.println(dateTime);
}catch(Exception ex){
ex.printStackTrace();
}
Java MySQL 数据类型对照
类型名称 | 显示长度 | 数据库类型 | JAVA 类型 | JDBC 类型索引 (int) | 描述 |
VARCHAR | L+N | VARCHAR | java.lang.String | 12 | |
CHAR | N | CHAR | java.lang.String | 1 | |
BLOB | L+N | BLOB | java.lang.byte[] | -4 | |
TEXT | 65535 | VARCHAR | java.lang.String | -1 | |
INTEGER | 4 | INTEGER UNSIGNED | java.lang.Long | 4 | |
TINYINT | 3 | TINYINT UNSIGNED | java.lang.Integer | -6 | |
SMALLINT | 5 | SMALLINT UNSIGNED | java.lang.Integer | 5 | |
MEDIUMINT | 8 | MEDIUMINT UNSIGNED | java.lang.Integer | 4 | |
BIT | 1 | BIT | java.lang.Boolean | -7 | |
BIGINT | 20 | BIGINT UNSIGNED | java.math.BigInteger | -5 | |
FLOAT | 4+8 | FLOAT | java.lang.Float | 7 | |
DOUBLE | 22 | DOUBLE | java.lang.Double | 8 | |
DECIMAL | 11 | DECIMAL | java.math.BigDecimal | 3 | |
BOOLEAN | 1 | 同 TINYINT | |||
ID | 11 | PK (INTEGER UNSIGNED) | java.lang.Long | 4 | |
DATE | 10 | DATE | java.sql.Date | 91 | |
TIME | 8 | TIME | java.sql.Time | 92 | |
DATETIME | 19 | DATETIME | java.sql.Timestamp | 93 | |
TIMESTAMP | 19 | TIMESTAMP | java.sql.Timestamp | 93 | |
YEAR | 4 | YEAR | java.sql.Date | 91 |
对于 bolb,一般用于对图片的数据库存储,原理是把图片打成二进制,然后进行的一种存储方式,在 java 中对应 byte[]数组。
对 Boolean 类型的解释
mysql 不支持 bool 类型。
1 2 3 4 5 |
|
这样可以创建成功,但检查表结构会发现 mysql 把它替换成 tinyint (1)。
即当把一个数据设置成 bool 类型的时候,数据库会自动转换成 tinyint (1) 的数据类型,其实这个就是变相的 bool。 默认值也就是 1,0 两种,分别对应了 bool 的 true 和 false
在 Java 对应的 POJO 类中,可以根据实际情况使用 java.lang.Boolean 或者 java.lang.Integer。
转自:
http://langgufu.iteye.com/blog/2202744
https://yq.aliyun.com/articles/38115
今天关于Java 复习和十三---- 多线程的介绍到此结束,谢谢您的阅读,有关-1-5 java 多线程 概念 进程 线程区别联系 java 创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock 锁 sleep () 和 wait () 方法的区别 为什么 wait...、0005--java 多线程、AG 百家乐最新官网《 787977.tv 蝙蝠 14735340 》java 并发编程 (2):Java 多线程 - java.util.concurrent 高级工具、java 中的日期类型:java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp 区别和总结等更多相关知识的信息可以在本站进行查询。
本文标签: