一、java
网络编程
Socket:
Socket(套接字)封装了TCP协议的通讯细节,使得我们使用它可以与服务端建立网络链接,并通过 它获
取两个流(一个输入一个输出),然后使用这两个流的读写操作完成与服务端的数据交互
ServerSocket :
ServerSocket运行在服务端,作用有两个:
1:向系统申请服务端口,客户端的Socket就是通过这个端口与服务端建立连接的。
2:监听服务端口,一旦一个客户端通过该端口建立连接则会自动创建一个Socket,并通过该
Socket与客户端进行数据交互
Socket提供了两个重要的方法:
OutputStream getOutputStream()
该方法会获取一个字节输出流,通过这个输出流写出的字节数据会通过网络发送给对方。
InputStream getInputStream()
通过该方法获取的字节输入流读取的是远端计算机发送过来的数据
二、
多线程
线程:
一个顺序的单一的程序执行流程就是一个线程。代码一句一句的有先后顺序的执行。
多线程:
多个单一顺序执行的流程并发运行。造成
"
感官上同时运行
"
的效果
1.创建线程有两种方式:
方式一
:
继承
Thread
并重写
run
方法
public class ThreadDemo1 {
public static void main(String[] args) throws IOException {
Thread t1 = new Tread1();
Thread t2 = new Thread2();
t1.start();
t2.start();
}
}
class Tread1 extends Thread{
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(111);
}
}
}
class Thread2 extends Thread{
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(222);
}
}
}
方式二:实现Runnable接口单独定义线程任务
public class ThreadDemo1 {
public static void main(String[] args) throws IOException {
Runnable r1 = new Runnable1();
Runnable r2 = new Runnable2();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
class Runnable1 implements Runnable{
@Override
public void run() {
System.out.println("任务1");
}
}
class Runnable2 implements Runnable{
@Override
public void run() {
System.out.println("任务2");
}
}
2.匿名内部类形式的线程创建
public class ThreadDemo1 {
public static void main(String[] args) throws IOException {
Thread t1 = new Thread(){
@Override
public void run() {
System.out.println(111);
}
};
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println(222);
}
};
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
}
3.
线程提供了一个方法:
static Thread currentThread()
该方法可以获取运行这个方法的线程
四.线程
API
获取线程相关信息的方法:
public class ThreadInfoDemo {
public static void main(String[] args) throws IOException {
//获取主线程
Thread main = Thread.currentThread();
//获取线程的名字
String name = main.getName();
//获取线程的唯一标识
long id = main.getId();
//获取线程的优先级
int priority = main.getPriority();
//判断线程是否活着
boolean isAlive = main.isAlive();
//判断线程是否是守护线程
boolean isDaemon = main.isDaemon();
//判断线程是否被中断了
boolean isInterrupted = main.isInterrupted();
}
}
线程有10个优先级,使用整数1-10表示
1为最小优先级
,10
为最高优先级
.5
为默认值
调整线程的优先级可以最大程度的干涉获取时间片的几率.
优先级越高的线程获取时间片的次
数越多
,
反之则越少
sleep
阻塞
线程提供了一个静态方法
:
static void sleep(long ms)
使运行该方法的线程进入阻塞状态指定的毫秒
,
超时后线程会自动回到
RUNNABLE
状态等待再次获
取时间片并发运行
public class SleepDemo {
public static void main(String[] args) {
System.out.println("程序开始");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("程序结束");
}
}
1.守护线程
守护线程是通过普通线程调用
setDaemon(boolean on)
方法设置而来的
,
因此创建上与普通线程无
异
.
守护线程的结束时机上有一点与普通线程不同
,
即
:
进程的结束
.
进程结束
:
当一个进程中的所有普通线程都结束时
,
进程就会结束
,
此时会杀掉所有正在运行的守护线
程
public class DaemonThreadDemo {
public static void main(String[] args) {
Thread zhangsan = new Thread(){
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("张三在跑步");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println("张三跑完了");
}
};
Thread lisi = new Thread(){
@Override
public void run() {
while (true) {
System.out.println("李四在跑步");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
};
zhangsan.start();
lisi.setDaemon(true);//设置守护线程必须在线程启动前
lisi.start();
}
}
多线程并发安全问题
当多个线程并发操作同一临界资源
,
由于线程切换时机不确定
,
导致操作临界资源的顺序出现混乱严重时可能导
致系统瘫痪
.
临界资源
:
操作该资源的全过程同时只能被单个线程完成
synchronized
有两种使用方式
在方法上修饰
,
此时该方法变为一个同步方法
同步块
,
可以更准确的锁定需要排队的代码片段
同步块
有效的缩小同步范围可以在保证并发安全的前提下尽可能的提高并发效率
.
同步块可以更准确的控制需要
多个线程排队执行的代码片段
.
在静态方法上使用
synchronized
当在静态方法上使用
synchronized
后
,
该方法是一个同步方法
.
由于静态方法所属类
,
所以一定具有同步效果
public class SyncDemo {
public static void main(String[] args) {
Thread t1 = new Thread(){
@Override
public void run() {
Aoo.doSome();
}
};
Thread t2 = new Thread(){
@Override
public void run() {
Aoo.doSome();
}
};
t1.start();
t2.start();
}
}
class Aoo{
public synchronized static void doSome(){
Thread t = Thread.currentThread();
try {
System.out.println(t.getName()+":正在执行方法");
Thread.sleep(5000);
System.out.println(t.getName()+":正在执行方法");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
五、集合框架
什么是集合?
集合与数组一样
,
可以保存一组元素
,
并且提供了操作元素的相关方法
,
使用更方便
Collection是所有集合的顶级接口
Collection
下面有两个常见的子接口
:
java.util.List:
线性表
.
是可重复集合
,
并且有序
java.util.Set:
不可重复的集合
,
大部分实现类是无序的
public class CollectionDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("1");
c.add("张三");
c.add("one");
System.out.println(c);
//返回当前集合元素的个数
int size = c.size();
//判断当前集合是否为空集
boolean isEmpty = c.isEmpty();
//清空集合
c.clear();
}
}
集合与元素equals方法相关的方法
public class CollectionDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("1");
c.add("张三");
c.add("one");
String name = "张三";
//boolean contains(Object o)
//判断当前集合是否包含给定元素,这里判断的依据是给定元素是否与集合现有元素存在equals比较为true的情况
boolean contains = c.contains(name);
System.out.println(contains);//true
//remove用来从集合中删除给定元素,删除的也是与集合中equals比较 为true的元素
c.remove(name);
System.out.println(c);
}
}
集合间的操作
public class CollectionDemo {
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add("java");
c1.add("c++");
c1.add(".net");
System.out.println("c1:"+c1);
Collection c2 = new HashSet();//不可重复集合
c2.add("android");
c2.add("ios");
c2.add("java");
System.out.println("c2:"+c2);
//将c2的所有元素添加到c1当中
c1.addAll(c2);
System.out.println("c1:"+c1);
System.out.println("c2:"+c2);
Collection c3 = new ArrayList();
c3.add("android");
c3.add("c++");
c3.add("php");
//判断当前集合是否包含给定集合中的所有元素
boolean containsAll = c1.containsAll(c3);
System.out.println("c1是否包含c3的所有元素:"+containsAll);
//c1.retainAll(c3);仅保留c1中与c3的共有元素。取交集
//删除c1中与c3的共有元素。删除交集
c1.removeAll(c3);
}
}
集合的遍历
Collection
提供了统一的遍历集合方式
:
迭代器模式
Iterator iterator()该方法会获取一个用于遍历当前集合元素的迭代器
.
public class IteratorDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("one");
c.add("#");
c.add("two");
c.add("#");
c.add("three");
c.add("#");
c.add("four");
c.add("#");
c.add("five");
System.out.println(c);
Iterator it = c.iterator();
//boolean hasNext()判断当前集合是否还有下一个元素可以遍历
while(it.hasNext()){
//E next()
//使迭代器向后移动到下一个元素的位置并获取该元素
String str = (String)it.next();
System.out.println(str);
if("#".equals(str)){
//迭代器要求在遍历的过程中不能通过集合的方法增删元素否则会抛出异常!
//c.remove(str);
//迭代器提供的remove可以删除迭代器当前位置表示的集合元素
it.remove();
}
}
System.out.println(c);
}
}
增强型for循环
格式:
for(
元素类型 变量名
:
集合或数组
){
循环体
}
public class NewForDemo {
public static void main(String[] args) {
String[] array = {"one","two","three","four","five"};
for(int i=0;i<array.length;i++){
String str = array[i];
System.out.println(str);
}
/*
新循环是编译器认可的,编译器会将它改为传统的for循环来遍历数组。
*/
for(String str : array){
System.out.println(str);
}
}
}
泛型
泛型也称为参数化类型,允许我们在使用一个类时指定它里面属性的类型
泛型被广泛应用于集合中,用来指定集合中的元素类型
支持泛型的类在使用时如果未指定泛型,那么默认就是原型Object
List集:get()
与
set()
public class ListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
System.out.println(list);
//E get(int index)
//获取指定下标处对应的元素
//E set(int index,E e)
//将给定的元素e存入下标index处,返回值为该位置原有的元素。
String str = list.get(2);
System.out.println(str);
//由于可以通过下标获取元素,因此普通for循环可以遍历List集合元素
for (int i=0;i<list.size();i++){
str = list.get(i);
System.out.println(str);
}
System.out.println(list);
String old = list.set(2,"six");
System.out.println(list);
System.out.println(old);
}
}
集合与数组的转换
Collection
提供了一个方法
:
toArray
,
可以将当前集合转换为一个数组
public class ToArrayDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
System.out.println(list);
String[] array = list.toArray(new String[list.size()]);
System.out.println(array.length);
System.out.println(Arrays.toString(array));
}
}