1.序列化流
将对象写入文件
package learn;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
public class ObjectOutDemo {
public static void main(String[] args) {
ObjectOutputStream objectOutputStream = null;
Person person = new Person(22, "wyx");
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream("G:/text.txt"));
objectOutputStream.writeObject(person);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(objectOutputStream != null){
try {
objectOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
注意对象要实现Serializable接口
读取对象,同样也要实现Serializable接口
package learn;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInDemo {
public static void main(String[] args) {
ObjectInputStream objectInputStream = null;
try {
objectInputStream = new ObjectInputStream(new FileInputStream("G:/text.txt"));
Object readObject = objectInputStream.readObject();
Person p = (Person) readObject;
System.out.println(p.getAge());
System.out.println(p.getName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(objectInputStream!=null){
try {
objectInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
如果对象发生了改变,那么反序列化就不能成功
需要给对象固定一个serialVersionUID
这样对象发生了改变依然能够反序列化
如果需要多个对象序列化,一定要放在集合中
2.线程
线程的两种创造方式
2.1继承Thread类
需要重写run方法
package learn;
public class ThreadDemo extends Thread {
public void run() {
for (int i = 0; i < 11; i++) {
System.out.println(this.getName() + "下载了" + i + "%");
}
}
}
package learn;
public class ThreadTest {
public static void main(String[] args) {
ThreadDemo threadDemo = new ThreadDemo();
threadDemo.start();
ThreadDemo threadDemo2 = new ThreadDemo();
threadDemo2.start();
}
}
2.2实现Runnable接口来创建线程
需要重新run方法
package learn;
public class ThreadTest2 implements Runnable {
public String name;
public ThreadTest2(String name) {
this.name = name;
}
public void run() {
for (int i = 0; i < 11; i++) {
System.out.println(this.name + "下载了" + i + "%");
}
}
}
package learn;
public class ThreadTest {
public static void main(String[] args) {
Thread thread = new Thread(new ThreadTest2("线程1"));
Thread thread2 = new Thread(new ThreadTest2("线程2"));
thread.start();
thread2.start();
}
}
线程的并发执行会存在安全性问题,可能会出现多个线程同时访问一个资源的情况,所以需要给资源上锁。
以买票为例
package learn;
public class TicketDemo extends Thread {
private String name;
static int ticket = 100;
public TicketDemo(String name) {
this.name = name;
}
public void run() {
while(ticket > 0){
System.out.println(this.name + "正在卖第" + ticket-- + "票");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package learn;
public class TicketTest {
public static void main(String[] args) {
TicketDemo ticketDemo1 = new TicketDemo("窗口1");
TicketDemo ticketDemo2 = new TicketDemo("窗口2");
TicketDemo ticketDemo3 = new TicketDemo("窗口3");
TicketDemo ticketDemo4 = new TicketDemo("窗口4");
ticketDemo1.start();
ticketDemo2.start();
ticketDemo3.start();
ticketDemo4.start();
}
}
如果不上锁发现会出现同时访问的情况
package learn;
public class TicketDemo extends Thread {
private String name;
static int ticket = 100;
static Object object = new Object(); //锁
public TicketDemo(String name) {
this.name = name;
}
public void run() {
while(ticket > 0){
synchronized (object) { //可能同时被多个资源访问的代码块
System.out.println(this.name + "正在卖第" + ticket-- + "票");
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package learn;
public class TicketDemo extends Thread {
private String name;
static int ticket = 100;
static Object object = new Object();
public TicketDemo(String name) {
this.name = name;
}
public void run() {
while (ticket > 0) {
saleticket();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static synchronized void saleticket() {
System.out.println(Thread.currentThread().getName()+ "正在卖第" + ticket-- + "票");
}
}
package learn;
public class TicketTest {
public static void main(String[] args) {
TicketDemo ticketDemo1 = new TicketDemo("窗口1");
TicketDemo ticketDemo2 = new TicketDemo("窗口2");
TicketDemo ticketDemo3 = new TicketDemo("窗口3");
TicketDemo ticketDemo4 = new TicketDemo("窗口4");
ticketDemo1.start();
ticketDemo2.start();
ticketDemo3.start();
ticketDemo4.start();
}
}
第二种方式
package learn;
public class TicketDemo1 implements Runnable{
int ticket = 100;
Object object = new Object();
public void run() {
while(ticket > 0){
synchronized (object) {
System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket-- + "票");
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
默认是this为锁
package learn;
public class TicketDemo1 implements Runnable{
int ticket = 100;
Object object = new Object();
public void run() {
while(ticket > 0){
saleticket();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public synchronized void saleticket() {
if(ticket > 0){
System.out.println(Thread.currentThread().getName()+ "正在卖第" + ticket-- + "票");
}
}
}
package learn;
public class TicketTest {
public static void main(String[] args) {
TicketDemo1 ticketDemo1 = new TicketDemo1();
Thread thread1 = new Thread(ticketDemo1,"窗口1");
Thread thread2 = new Thread(ticketDemo1,"窗口2");
Thread thread3 = new Thread(ticketDemo1,"窗口3");
Thread thread4 = new Thread(ticketDemo1,"窗口4");
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
3.线程间的通信
- 线程中通信共享数据一定要有同步代码块synchronized
- 一定要有wait和notify,成对出现
- 生产者和消费者的线程实现是再while(true)中
package learn;
public class Basket {
public boolean isEmpty;
}
package learn;
public class Produce extends Thread{
private Basket basket;
public Produce(Basket basket) {
this.basket = basket;
}
public void run() {
while (true) {
synchronized (basket) {
if(!basket.isEmpty){
try {
basket.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("生产者生产了水果");
basket.isEmpty = false;
basket.notify();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package learn;
public class Consumer extends Thread{
private Basket basket;
public Consumer(Basket basket) {
this.basket = basket;
}
public void run() {
while (true) {
synchronized (basket) {
if(basket.isEmpty){
try {
basket.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费者消费了水果");
basket.isEmpty = true;
basket.notify();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package learn;
public class Test {
public static void main(String[] args) {
Basket basket = new Basket();
Produce produce = new Produce(basket);
Consumer consumer = new Consumer(basket);
produce.start();
consumer.start();
}
}
可以通过setPriority来设置线程的优先级,默认是5,最高10,最低1
让出线程
加入线程
设置守护线程
thread1.setDaemon(true);
主线程结束后,子线程也会结束