进程
定义:操作系统中CPU被分为一个个时间片,所有进程都在时间片上轮换执行,并且同一个时间片只能执行一个进程
进程和CPU的关系:
线程
定义:在进程中并行执行的多项任务
线程,进程,CPU的关系:
创建线程方法1:
public static void main(String[] args) {
//创建test2的实例
test2 t1 = new test2();
//开启线程
t1.start();
}
static class test2 extends Thread{//继承Thread类
@Override
public void run() {System.out.println("1");}//重写run方法
}
}
创建线程方法2:
public static void main(String[] args) {
//封装run方法,让run方法可以放入到线程中执行
test3 t = new test3();
//创建Thread的实例,并将t实例放入其中
Thread t1 = new Thread(t);
//开启线程
t1.start();
}
//实现Runnable接口,并且runnable不是线程,它只是用于封装可以在线程中执行的代码,只有Thread是线程
static class test3 implements Runnable{
@Override
public void run() {//重写run方法
Thread t = Thread.currentThread(); //获取正在执行这行代码的当前线程实例
String s = t.getName();
System.out.println(s);
}
}
线程的状态
新生 —> 可执行 —> 执行 —> 消亡
线程状态图:
线程同步锁
定义:线程同步锁(Synchronized)当一个线程拿到线程同步锁时,其他线程要等待该线程执行结束将线程同步锁释放后去争夺线程同步锁,只有抢到线程同步锁才能够执行。
作用:保证线程安全
注意:如果添加了线程同步锁,那么该代码同一时间只能够有一个线程执行。
synchronize监视器原理:
死锁的原理:
多线程数据访问冲突模板:
测试代码:
public class test1 {
static char[] a = {'*','*','*','*','*'};
static char c = '-';
public static void main(String[] args) {
Thread t1 = new Thread() {@Override
public void run() {
while (true) {for (int i = 0; i < a.length; i++) {a[i] = c;}
c = (c=='-'?'*':'-');}}};
Thread t2 = new Thread() {@Override
public void run() {
while (true) {System.out.println(Arrays.toString(a));}}};
t1.start();
t2.start();
}
}
客户端与服务端
public class 客户端 {
public static void main(String[] args) throws Exception {
//与服务端创建连接,端口号与服务器的端口号一致
Socket s = new Socket("176.201.107.39",8000);
//获取Socket对象的输入流和出输出流
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
//向服务端发送hello
out.write("hello".getBytes());
//遍历接收服务端传来的world
for(int i=0; i<5;i++) {
char read = (char) in.read();
System.out.print(read);}
//关闭连接
s.close();
}
}
public class 服务端 {
public static void main(String[] args) throws Exception {
//创建服务器端口,端口号设置为8000
ServerSocket ss = new ServerSocket(8000);
//暂停,等待客户端发起连接并且简历连接通道,获得Socket对象
Socket accept = ss.accept();
//获取Socket对象的输入流和输出流
InputStream in = accept.getInputStream();
OutputStream out = accept.getOutputStream();
//遍历五次,接收客户端传来的hello
for(int i=0;i<5;i++) {
char read = (char) in.read();
}
//向客户端传递world
out.write("world".getBytes());
//断开客户端连接
accept.close();
//断开服务端连接
ss.close();
}
}
客户端与服务端___回声
public class 服务端 {
public void a() {
//创建线程
new Thread() {@Override
public void run() {
try {
//创建连接
ServerSocket ss = new ServerSocket(8000);
//创建通信线程
Socket accept = ss.accept(); 通信 t = new 通信(accept); t.start();
} catch (IOException e) {e.printStackTrace();}}}.start();
}
public static void main(String[] args) {
服务端 f = new 服务端();
f.a();
}
}
public class 客户端 {
public static void main(String[] args) throws Exception {
//创建连接
Socket socket = new Socket("176.201.107.39",8000);
//获取输入流输出流
BufferedReader in =
new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out =
new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
//不断向服务端发送数据
while(true) {
String str = new Scanner(System.in).nextLine();
out.println(str); out.flush(); in.readLine();
}
}
}
public class 通信 extends Thread{
private Socket s;
private String str;
public 通信(Socket s) {super(); this.s = s;}
//创建线程
@Override
public void run() {
try {
//获取输出流和输入流
BufferedReader in =
new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter out =
new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
//当str不为空时,不断的接收客户端数据
while((str = in.readLine()) != null) {out.println(); out.flush();}
} catch (IOException e) {e.printStackTrace();}
}
}
聊天室
public class 服务端 {
/*
* 因为是聊天室,不确定有多少人,该集合只用于遍历,向所有人发送信息,不涉及增删改
* 所以使用ArrayList来存储通信线程。
*/
static ArrayList<通信> list = new ArrayList<>();
//创建launch方法
public void launch() {
//创建线程
new Thread() {@Override
//重写run方法
public void run() {
//建立连接
try {
ServerSocket ss = new ServerSocket(8000);
//一直创建通信线程
while(true) {Socket accept = ss.accept(); 通信 t = new 通信(accept); t.start();}
} catch (IOException e) {e.printStackTrace();}
}}.start();
}
public static void main(String[] args) {
//创建实例
服务端 f = new 服务端();
//调用launch方法
f.launch();
}
}
public class 客户端 {
//创建Socket变量
private Socket s;
//创建String name变量
private String name;
//创建BufferedReader变量
private BufferedReader in;
//创建PrintWriter变量
private PrintWriter out;
//创建集合
LinkedList<String> list = new LinkedList<>();
//创建Boolean变量
private Boolean a;
//创建launch方法
public void launch() {
//创建连接
try {
s = new Socket("176.201.107.39",8000);
//创建BufferedReader实例
in = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
//创建PrintWriter实例
out = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
//输入名称
name = new Scanner(System.in).nextLine();
//输出名称
out.println();
//刷出缓存
out.flush();
} catch (Exception e) {e.printStackTrace();}
//创建发送线程,创建output方法
new Thread() {@Override
public void run() {output();
}}.start();
//创建接收线程,创建input方法
new Thread() {@Override
public void run() {input();
}}.start();
//创建打印线程,创建print方法
new Thread() {@Override
public void run() {print();
}}.start();
}
//print方法
protected void print() {
//一直接收
while(true) {
//当集合大小为0或者b为true
synchronized (list) {
while(list.size()==0 || a==true) {
//集合等待
try {list.wait();} catch (InterruptedException e) {e.printStackTrace();}}
//移除集合中第一个数据
list.removeFirst();}}}
//创建input方法
protected void input() {
String line;
//当从服务端接受的数据不为null时
try {
while((line = in.readLine())!=null) {
//从集合中添加数据并且通知等待的线程
list.add(line); list.notifyAll();}
} catch (IOException e) {e.printStackTrace();}}
protected void output() {
//一直接收
while(true) {
//按回车输入内容
new Scanner(System.in).nextLine();
//打开开关
a = true;
//输入聊天内容
String s = new Scanner(System.in).nextLine();
//输出 刷出缓存 关闭开关
out.println(s); out.flush(); a = true;
//提醒线程
synchronized (list) {list.notifyAll();}}}}
public class 通信 extends Thread{
//创建Socket变量
private Socket s;
//创建BufferedReader变量
private BufferedReader in;
//创建PrintWriter变量
private PrintWriter out;
//创建String name变量
private String name;
//创建含Socket构造
public 通信(Socket s) {super();this.s = s;}
//创建send方法,发给当前客户端
public void send(String s) {out.println(s); out.flush();}
//创建sendAll方法,发给所有客户端
public void sendAll(String s) {for(通信 list : 服务端.list) {list.send(s);}}
@Override
//重写run方法
public void run() {
try {
//获取BufferedReader实例
in = new BufferedReader(new InputStreamReader(s.getInputStream(),"UTF-8"));
//获取PrintWriter实例
out = new PrintWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));
//接收客户端输入的名称
name = new Scanner(System.in).nextLine();
//群发一个欢迎信息
sendAll("欢迎 "+name+" 进入聊天室");
//将自己添加到list集合中
服务端.list.add(this);
//创建一个String变量
String line;
//从客户端接收数据,群发,直到接收到null结束
while((line = in.readLine()) != null) {sendAll(name+" 说:"+line);}
//将自己从集合中移除
服务端.list.remove(this);
//群发一个下线信息
sendAll(name+" 已下线");
} catch (IOException e) {e.printStackTrace();}}}